Функция обратная WHERE()

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 4615
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 6 раз
Поблагодарили: 37 раз

Функция обратная WHERE()

Сообщение finsoftrz »

Конкретно и нудно, да ладно сказки рассказывать. :-) Мы тут недавно несколько дней только с изменениями в порядке учета аванса по заработной плате разбирались. Налоговики приняли, написали письмо с разъяснением, даже пару примеров включили. А как на практике применить, никто точно не знает, вопросов по конкретным ситуациям много, а все тупо перепостят это письмо, добавив воды от себя. Потом 1с выпустило многостраничную инструкцию, как в их системе работать. А там несколько вариантов, типа, на ваше усмотрение, выбирайте сами. Основная рекомендация это использовать расчет зарплаты за первую и вторую половину месяца. Это у них еще раньше было реализовано, видимо, по запросу каких-то крупных контор. К законодательству отношения не имеет, для внутренних нужд, а в этом году приспособили. Скажу только, что после разбора ситуации, у нас была использована несколько иная методика, отличная от тех, которые предлагает 1с. Причем некоторые вопросы, особенно касающиеся переходного периода, так и остаются без разъяснений. Я бы даже сказал, что налоговики сами нарушают налоговое законодательство, но судиться с ними никто лишний раз не хочет, приходится подстраиваться.
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 7373
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 13 раз
Поблагодарили: 48 раз

Функция обратная WHERE()

Сообщение Игорь Столяров »

Вот зарплата - да. Там всегда был тёмный лес, а потом к нему добавили автоматизацию и фонды.
Вот здесь действительно место тонким настройкам и что-то вечно пилящих ботанов и т.д. :)
За теми кто отстал - не возвращаться. (С) Кодекс
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 4615
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 6 раз
Поблагодарили: 37 раз

Функция обратная WHERE()

Сообщение finsoftrz »

Не поверите, ветис хлеще. Там при разборе xml порой вылезают такие вещи, которые нигде не задокументированы.
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 7373
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 13 раз
Поблагодарили: 48 раз

Функция обратная WHERE()

Сообщение Игорь Столяров »

Попробуем формализовать задачу сабжа в частности (и парсинга XML вообще).

1. При парсинге нужно как-то сопоставить конкретный тег <X1/> в XML и
поле с именем F1 в структуре данных GROUP (или записи QUEUE).

2. Если у нас все имена тегов в XML уникальные - то всё просто.
Задаём "имя поля" = "имя тега" и получаем данные из XML в GROUP.

3. Если имена тегов в XML не уникальны - нужно учитывать их место в XML.
Для этого нужно получить полное имя от корневого тега (или группы тегов).
Технически - это простая задача, т.к. понятие ParentTag заложено в XML.

4. Далее нужно как-то определить такое же полное имя тега в структуре GROUP.
Самое простое - это тупо прописать полное имя в Name('G1\G2\G3 ...') и далее
сравнивать его с полным именем тега в XML.
Минусы:
- Ограничение длины Name в 100 символов;
- Отсутствие возможности использовать вложенные типовые структуры данных
(для каждого поля нужно задать полное фиксированное уникальное имя) ;
- монстрообразные трудно-модифицируемые текстовые блоки с именами;

5. И вот здесь возникает задача получения функции AntiWhere(GROUP,NumberField),
которая вернёт полное именя поля с учётом вложенности в GROUP для сравнения
с полным именем тега в XML структуре.

Как-то так ! :)
За теми кто отстал - не возвращаться. (С) Кодекс
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 4615
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 6 раз
Поблагодарили: 37 раз

Функция обратная WHERE()

Сообщение finsoftrz »

Я уже писал, может пропустили, что полное имя от якорного тега в name прописывается, если используется загрузка в очередь или группу одним оператором. Это покрывает большую часть потребностей. Для сложных случаев, когда используется прямое встраивание скриптов, этого делать не надо. Можно вообще имя не указывать, а прописать имя поля непосредственно в скрипте. Если есть вложенные структуры, то они парсятся в несколько соответствующих групп/кьюшек. В скрипте это делается просто и тривиально.
Если использовать парсер из поставки клариона, то там, наверно, можно организовать нечто подобное, только сложнее и с ограничениями. Тут Вам карты в руки. :-)
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 4615
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 6 раз
Поблагодарили: 37 раз

Функция обратная WHERE()

Сообщение finsoftrz »

Можно попробовать устанавливать соответствие с помощью специального метода класса. Вот пример загрузки из xls/xlsx, это не xml, но демонстрирует технику, которую можно применить и в случае xml. Может, пригодится.

Код: Выделить всё

form_r  routine
   DATA
fsMOL  &FsMsOffice
fsOOL  &FsOpenOffice

lor:queue queue, pre()
lor:kod      string(20), name('cKod')
lor:sumFir   string(20), name('cSumF')
lor:sumKli   string(20), name('cSumK')
lor:name     string(150), name('cName')
.

lor:i        long
lor:err      byte
lor:sumDoc   real

   CODE

   if Loc:FileName=''
      FsMessagePr('Не задан файл!')
      select(?Loc:FileName)
      exit
   elsif ~exists(Loc:FileName)
      FsMessagePr('Не найден файл!')
      select(?Loc:FileName)
      exit
   .

   if Loc:ColumKod=0 or Loc:ColumDolgFirma=0 or Loc:ColumDolgKlient=0 or Loc:ColumName=0
      FsMessagePr('Не заданы номера для всех колонок!')
      exit
   .

   if Loc:IDFirma=0
      FsMessagePr('Не задана фирма!')
      exit
   .
   if Loc:IDRRasch=0
      FsMessagePr('Не задан раздел расчетов!')
      exit
   .
   if Loc:IDZatr=0
      FsMessagePr('Не задан вид затрат!')
      exit
   .
   if Loc:Date=0
      FsMessagePr('Не задана дата!')
      exit
   .
   if GetDateZapr(Loc:Date)=1
      FsMessagePr('Дата в закрытом периоде!')
      exit
   .

   if Loc:RowBeg=0 and Loc:TypeImport=0
      Loc:RowBeg=1
      display(?Loc:RowBeg)
   .

   if FsMessageQ('Загрузить долги по взаиморасчетам?',1)<>1
      exit
   .

   if Loc:TypeImport=0   !excel
      fsMOL &= new(FsMsOffice)
      fsMOL.init(GetNameTmp(FsAccess:ActiveUserDir,'vbs',0),GetNameTmp(FsAccess:ActiveUserDir,'txt',0))

      fsMOL.ExcelConnect
      fsMOL.ExcelOpen(Loc:FileName)

      fsMOL.ExcelMapQueueAdd('cKod',Loc:ColumKod,1,'')
      fsMOL.ExcelMapQueueAdd('cSumF',Loc:ColumDolgFirma,0,'')
      fsMOL.ExcelMapQueueAdd('cSumK',Loc:ColumDolgKlient,0,'')
      fsMOL.ExcelMapQueueAdd('cName',Loc:ColumName,0,'')

      fsMOL.ExcelGetRangeString(Loc:RowBeg)
      fsMOL.ExcelDisConnect
      fsMOL.MakeScript(1,lor:queue)

      fsMOL.kill
      dispose(fsMOL)
   else   !calc
      fsOOL &= new(FsOpenOffice)
      fsOOL.init(GetNameTmp(FsAccess:ActiveUserDir,'vbs',0),GetNameTmp(FsAccess:ActiveUserDir,'txt',0))

      fsOOL.CalcConnect
      fsOOL.CalcOpen(Loc:FileName)

      fsOOL.CalcMapQueueAdd('cKod',Loc:ColumKod-1,1,'')
      fsOOL.CalcMapQueueAdd('cSumF',Loc:ColumDolgFirma-1,0,'')
      fsOOL.CalcMapQueueAdd('cSumK',Loc:ColumDolgKlient-1,0,'')
      fsOOL.CalcMapQueueAdd('cName',Loc:ColumName-1,0,'')

      fsOOL.CalcGetRangeString(Loc:RowBeg-1)
      fsOOL.CalcDisConnect(1)
      fsOOL.MakeScript(1,lor:queue)

      fsOOL.kill
      dispose(fsOOL)
   .

   if records(lor:queue)=0
      FsMessagePr('Данные не найдены!')
      exit
   .

   if FsLogout(1,3,DocRasch,FsLogTr)=0
      exit
   .
   lor:err=0

   loop lor:i=1 to records(lor:queue)
      get(lor:queue,lor:i)
      if numeric(lor:kod)=0
         cycle
      .
      lor:sumDoc=lor:sumFir-lor:sumKli
      if lor:sumDoc=0
         cycle
      .
      clear(kli:record)
      kli:kod=lor:kod
      get(Klients,Kli:keyKod)
      if error()
         FsMessagePr('Не найден контрагент (' & clip(lor:kod) & ') ' & clip(lor:name))
         lor:err=1
         break
      .

      clear(DRas:record)
      DRas:Date=loc:date
      DRas:Time=loc:time
      DRas:PeriodDoc=year(DRas:Date)
      DRas:IDKlientS=kli:id
      DRas:IDRRaschS=loc:idRRasch
      DRas:IDFirma=Loc:IDFirma
      DRas:IDZatr=loc:idZatr
      DRas:Sum=lor:sumDoc
      DRas:DocStatus=1
      if FsAdd:DocRasch(2)<>1
         lor:err=1
         break
      .
   .

   free(lor:queue)

   if lor:err=0
      FsCommit(1)
   else
      FsRollback(1)
   .

C6/C11, ШВС, tps/btrieve.
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 7373
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 13 раз
Поблагодарили: 48 раз

Функция обратная WHERE()

Сообщение Игорь Столяров »

finsoftrz писал(а): 28 Февраль 2023, 8:41 Можно вообще имя не указывать, а прописать имя поля непосредственно в скрипте.
Я это обсуждение прекрасно помню.
Встраивание в код (программы, скрипта) фиксированных имён тегов для распарса конкретного XML -
этот вариант вообще не интересен. Это не парсер, а специализированный разбор текстовых файлов.

Парсер должен получить на входе произвольные XML и GROUP и заполнить данными из XML поля GROUP.
Технически - это может быть API или скрипт, в памяти или через диск / файлы - неважно.

Но смысл парсера как в классической машине Тьюринга:
- в зависимости от задачи изменяются данные, но всегда один процессор (исполнитель).
За теми кто отстал - не возвращаться. (С) Кодекс
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 4615
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 6 раз
Поблагодарили: 37 раз

Функция обратная WHERE()

Сообщение finsoftrz »

Плохо понимаю это. В любом случае есть привязка к именам тэгов конкретного вида xml. Программа в итоге должна понимать, что есть что. Привязать можно либо через name структуры, либо через вызов метода класса. Я видел как-то у CapeSoft, Брюс целые выражения в name закатывал.
Скрипт vbscript условно можно сравнить с sql запросами. В sql указываются названия полей и таблиц, аналогично в скрипте в итоге указываются имена тэгов. Если используются драйвера, то они транслируют свой синтаксис в sql запросы. Аналогично у меня класс парсера транслирует вызовы методов в vbscript.
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 7373
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 13 раз
Поблагодарили: 48 раз

Функция обратная WHERE()

Сообщение Игорь Столяров »

finsoftrz писал(а): 28 Февраль 2023, 9:28 видел как-то у CapeSoft
Да. Вот это я хотел бы посмотреть - сейчас так и сделаю ...
За теми кто отстал - не возвращаться. (С) Кодекс
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 4615
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 6 раз
Поблагодарили: 37 раз

Функция обратная WHERE()

Сообщение finsoftrz »

Есть еще вариант убрать информацию о тэгах внутрь метода класса. То, есть, например, RulesEdo для эдо, RulesEgais для егаис и т.д. Там делаем привязку тэгов к кратким именам, которые затем используем в структурах. Я нечто подобное делаю сейчас с xpath в Егаис.
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 7373
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 13 раз
Поблагодарили: 48 раз

Функция обратная WHERE()

Сообщение Игорь Столяров »

Вот именно это место у нас требует преодоления стереотипов ! :)
Вы непременно хотите, что бы в решении любой задачи принял участие супер-программер,
который что-то там своей божественной рукой подправит или закостылит в классе / скрипте и т.д. ;)
И без него, ну никак. Так было. Но мы наш, мы новый мир построим и т.д. и т.п. :)
За теми кто отстал - не возвращаться. (С) Кодекс
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 4615
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 6 раз
Поблагодарили: 37 раз

Функция обратная WHERE()

Сообщение finsoftrz »

Что-то я нить разговора потерял. Вы хотите свой 1с написать, чтобы "конфигурасты" за вас прикладной код писали? Или просто пока что-то хотите? :idied:
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 7373
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 13 раз
Поблагодарили: 48 раз

Функция обратная WHERE()

Сообщение Игорь Столяров »

Ничего военного или даже нового я сделать не хочу.
Упрощённо (без вложенных списков):
------------------------------------------------
- Есть некий, произвольный XML файл;
- Мы описываем его структуру (GROUP);
- Вызываем парсер и получаем данные из XML в GROUP;
- Всё.

В принципе, так работает любой парсер. Например тот же cJSON.
За теми кто отстал - не возвращаться. (С) Кодекс
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 4615
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 6 раз
Поблагодарили: 37 раз

Функция обратная WHERE()

Сообщение finsoftrz »

Мда... Трудный случай. :dizzy:
C6/C11, ШВС, tps/btrieve.
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 7373
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 13 раз
Поблагодарили: 48 раз

Функция обратная WHERE()

Сообщение Игорь Столяров »

Как раз-таки здесь идея простая и ей 85 лет.
А какие ещё варианты ?
Делать отдельный парсер под каждую структуру XML ?
Задавать в имени каждого поля структуру данных текстом ?
За теми кто отстал - не возвращаться. (С) Кодекс
Ответить