Главная DISCLAIMER Ссылки Карта сайта Контакты
Главная arrow Вопросы разработки arrow Источники данных arrow Клас-парсер параметра проводки
Клас-парсер параметра проводки

В строке документа Акцента может быть показано произвольное количество данных. Решается легко добавлением параметров проводки.

Однако при решении учётных задач в форме первичного документа часто бывает необходимо показывать и сохранять редко используемые или вообще не востребованные в учёте данные, как то фамилии подписавших лиц, различные промежуточные и вспомогательные величины. При этом большое количество задействованных параметров сказывается на быстродействии формы и всей системы в целом. Примером может послужить Ведомость расчёта амортизации ОС, где из всех параметров значащим является только начисленная сумма износа, или вот подобный документ:

Форма

В предлагаемом решении все не особо важные данные собираются в один строковый параметр в формате "с разделителем". Использован класс - источник данных для редактора, поэтому проектирование формы происходит абсолютно прозрачно и ничуть не сложнее чем с использованием отдельного параметра для каждого числа.

В модуле формы просто объявляется класс и используется в таблицах документа. Рекомендую для номера фрагмента использовать номер, соответсвующий номеру колонки, а не по порядку, если вдруг в ходе развития проекта данные одного из столбцов будет необходимо связать с суммой, ценой или количеством по проводке.

Код использования экземпляра класса в таблице

  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

Тип данных может быть строка, целое, денежный или дата. Будет работать селектор выбора даты (календарик). К сожалению, внутри подобного класса нельзя реализовать селектор выбора товара или поставщика, нужно будет отдельно обрабатывать нажатие кнопки.

Это простой пример класса, более сложные варианты с вертикальными и горизонтальными итогами, автоматическим расчётом и пропорциональным распределением сумм в отдельных колонках используются в форма расчёта себестоимости.

 
След. »