Клас-парсер параметра проводки |
В строке документа Акцента может быть показано произвольное количество данных. Решается легко добавлением параметров проводки. Однако при решении учётных задач в форме первичного документа часто бывает необходимо показывать и сохранять редко используемые или вообще не востребованные в учёте данные, как то фамилии подписавших лиц, различные промежуточные и вспомогательные величины. При этом большое количество задействованных параметров сказывается на быстродействии формы и всей системы в целом. Примером может послужить Ведомость расчёта амортизации ОС, где из всех параметров значащим является только начисленная сумма износа, или вот подобный документ: В предлагаемом решении все не особо важные данные собираются в один строковый параметр в формате "с разделителем". Использован класс - источник данных для редактора, поэтому проектирование формы происходит абсолютно прозрачно и ничуть не сложнее чем с использованием отдельного параметра для каждого числа. В модуле формы просто объявляется класс и используется в таблицах документа. Рекомендую для номера фрагмента использовать номер, соответсвующий номеру колонки, а не по порядку, если вдруг в ходе развития проекта данные одного из столбцов будет необходимо связать с суммой, ценой или количеством по проводке. Код использования экземпляра класса в таблице tbl_en3.Range(001,5,001,8).DataSource="op.Trans(3,tbl_en3.BindRow-4).MiscBind(mscNo_TRS)" ' Наимен. и марка tbl_en3.Range(002,5,002,8).DataSource="op.Trans(3,tbl_en3.BindRow-4).Qty" ' Дней в хозяйстве tbl_en3.Range(003,5,003,8).DataSource="TrParaEd3.ValueCur(tbl_en3.BindRow-4,3)" ' Дней в ремонте tbl_en3.Range(004,5,004,8).DataSource="TrParaEd3.ValueCur(tbl_en3.BindRow-4,4)" ' Текущий случ.ремонт tbl_en3.Range(005,5,005,8).DataSource="TrParaEd3.ValueCur(tbl_en3.BindRow-4,5)" ' Средний tbl_en3.Range(006,5,006,8).DataSource="TrParaEd3.ValueCur(tbl_en3.BindRow-4,6)" ' Капитальный tbl_en3.Range(007,5,007,8).DataSource="TrParaEd3.ValueCur(tbl_en3.BindRow-4,7)" ' Ожидание ремонта .................... tbl_en3.Cell(9,002).DataSource="op.TransList(3).Qty" tbl_en3.Cell(9,003).DataSource="TrParaEd3.ColSum(3)" tbl_en3.Cell(9,004).DataSource="TrParaEd3.ColSum(4)" tbl_en3.Cell(9,005).DataSource="TrParaEd3.ColSum(5)" tbl_en3.Cell(9,006).DataSource="TrParaEd3.ColSum(6)" ............. Чтобы не делать пересчёт итогов таблицы при каждом событии пересчёта в форме, изменение значения параметра отслеживает сам класс, об удалении строки сообщаем классу явно Sub tbl_en3_OnBound(ByRef Lock) Dim col : col=tbl_en3.Col Dim row : row=tbl_en3.Row-4 ' 4 строки на шапку. If col=001 Then op.Trans(3,row).EntID=op.Trans(3,row).MiscBind(mscNo_TRS).Long1 op.TransList(3).Pack : TrParaEd3.CalcSum End If End Sub Текст класса ' использование "TrParaEd1.ValueCur(tbs.BindRow,5)" ' Номер параметра соотв.номеру колонки в таблице! '===================================================================================================== Dim TrParaEd1 : Set TrParaEd1=New opTrParamEditor : TrParaEd1.TrNo=1 Dim TrParaEd2 : Set TrParaEd2=New opTrParamEditor : TrParaEd2.TrNo=2 Dim TrParaEd3 : Set TrParaEd3=New opTrParamEditor : TrParaEd3.TrNo=3 'c' NANSI Class opTrParamEditor 'класс для редактирования по частям параметра op.Trans(trNo,row).AgTo Private arSum ' массив итогов по столбцам. Public TrNo Private Sub Class_Initialize : arSum=Array : End Sub Public Default Property Get ValueString(row,n) If row>op.TransList(TrNo).Rows Then Exit Property ' чтобы не показывал числа на последней пустой строке. ValueString=Token(op.Trans(TrNo,row).Params.Item("String1").Value2,n,"|") End Property Public Property Let ValueString(row,n,val) Dim trp : Set trp=op.Trans(TrNo,row).Params Dim ar : ar=Split(trp.Item("String1").Value2,"|") : If UBound(ar)<n-1 Then ReDim Preserve ar(n-1) ar(n-1)=Replace(val,"|","") trp.Item("String1").Value=Join(ar,"|") End Property Public Property Get ValueCur(row,n) If row>op.TransList(TrNo).Rows Then Exit Property ' чтобы не показывал числа на последней пустой строке. Dim s : s=Token(op.Trans(TrNo,row).Params.Item("String1").Value2,n,"|") If Len(s)=0 Then ValueCur=0 Else ValueCur=str2dbl(s) ' встроенная в 7 версию. End Property Public Property Let ValueCur(row,n,val) If Len(val)>0 Then If Not IsNumeric(val) Then Exit Property Dim trp : Set trp=op.Trans(TrNo,row).Params Dim ar : ar=Split(trp.Item("String1").Value2,"|") : If UBound(ar)<n-1 Then ReDim Preserve ar(n-1) ar(n-1)=Replace(val,"|","") trp.Item("String1").Value=Join(ar,"|") Call CalcSum() ' после любой записи числа - пересчёт всех итогов. End Property Public Property Get ValueLong(row,n) If row>op.TransList(TrNo).Rows Then Exit Property ' чтобы не показывал числа на последней пустой строке. Dim s : s=Token(op.Trans(TrNo,row).Params.Item("String1").Value2,n,"|") If Len(s)=0 Then ValueLong=0 Else If IsNumeric(s) Then ValueLong=CLng(s) Else ValueLong=0 End Property Public Property Let ValueLong(row,n,val) If VarType(val)=vbBoolean Then val=CLng(val) ' почему-то не проходит IsNumeric для булевых. If Len(val)>0 Then If Not IsNumeric(val) Then Exit Property Dim trp : Set trp=op.Trans(TrNo,row).Params Dim ar : ar=Split(trp.Item("String1").Value2,"|") : If UBound(ar)<n-1 Then ReDim Preserve ar(n-1) ar(n-1)=Replace(val,"|","") trp.Item("String1").Value=Join(ar,"|") Call CalcSum() ' после любой записи числа - пересчёт всех итогов. End Property Public Property Get ValueDate(row,n) If row>op.TransList(TrNo).Rows Then Exit Property ' чтобы не показывал числа на последней пустой строке. Dim s : s=Token(op.Trans(TrNo,row).Params.Item("String1").Value2,n,"|") ValueDate=JapanToDate(s) End Property Public Property Let ValueDate(row,n,val) If Len(val)>0 Then If Not IsDate(val) Then Exit Property Dim trp : Set trp=op.Trans(TrNo,row).Params Dim ar : ar=Split(trp.Item("String1").Value2,"|") : If UBound(ar)<n-1 Then ReDim Preserve ar(n-1) ar(n-1)=Replace(dtToJapan(val),"|","") trp.Item("String1").Value=Join(ar,"|") End Property Function dtToJapan(dt) If Not IsDate(dt) Then dtToJapan="00000000" : Exit Function If Len(dt)=0 Then dtToJapan="00000000" : Exit Function dtToJapan=Replace(FormatDate2(dt,"yyyy mm dd")," ","") End Function Function JapanToDate(s) If s="00000000" Then Exit Function Dim yy : yy=Left(s,4) : If Not IsNumeric(yy) Then Exit Function Dim mm : mm=Mid(s,5,2) : If Not IsNumeric(mm) Then Exit Function Dim dd : dd=Right(s,2) : If Not IsNumeric(dd) Then Exit Function JapanToDate=DateSerial(CLng(yy),CLng(mm),CLng(dd)) End Function Public Property Get ColSum(n) ' сумма колонки. If n>UBound(arSum) Then Call CalcSum() ' первый же запрос итога пересчитает всё. If n>UBound(arSum) Then ReDim Preserve arSum(n) ColSum=CCur(arSum(n)) End Property Sub CalcSum() ' пересчёт всех вертикальных итогов после изменения параметра. arSum=Array Dim row : For row=1 To op.TransList(TrNo).Rows Dim trp : Set trp=op.Trans(TrNo,row).Params Dim ar : ar=Split(trp.Item("String1").Value2,"|") If UBound(ar)<UBound(arSum) Then ReDim Preserve ar(UBound(arSum)) If UBound(arSum)<UBound(ar)+1 Then ReDim Preserve arSum(UBound(ar)+1) Dim n : For n=0 To UBound(ar) arSum(n+1)=arSum(n+1)+CCur(str2dbl(ar(n))) Next Next End Sub End Class Тип данных может быть строка, целое, денежный или дата. Будет работать селектор выбора даты (календарик). К сожалению, внутри подобного класса нельзя реализовать селектор выбора товара или поставщика, нужно будет отдельно обрабатывать нажатие кнопки. Это простой пример класса, более сложные варианты с вертикальными и горизонтальными итогами, автоматическим расчётом и пропорциональным распределением сумм в отдельных колонках используются в форма расчёта себестоимости. |
След. » |
---|