-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathw_report.PRG
3327 lines (3304 loc) · 152 KB
/
w_report.PRG
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
PARAMETERS f_shabl, f_othet, rep_config
rep_time=SECONDS()
ret_error=RTF_REPORT(m.f_shabl,m.f_othet,m.rep_config)
rep_time=SECONDS()-m.rep_time
? "Время выполнения: "+STR(INT(rep_time/60),3)+":"+CHRTRAN(STR(MOD(rep_time,60),2)," ","0")+" сек."
IF !EMPTY(m.ret_error)
=MESSAGEBOX(m.ret_error,16,"Ошибка")
ENDIF
RETURN m.ret_error
*############################################################################################
*############################################################################################
*############################################################################################
FUNCTION RTF_REPORT && формирование отчета на основе описанного RTF шаблона
PARAMETERS f_shabl, f_othet, rep_config
* f_shabl - файл шаблона
* f_othet - файл результата
* rep_config - Конфигурация запуска - может содержать любой набор из нижеперечисленных вариантов:
* [SHOW] - показать отчет
* [ADDF] - автоматически создавать файл результата с возрастающим номером, в случае, если не удается переписать файл
* [MERGE] - Объединить текущий результат с существующим файлом WORD. Исключает параметр [ADDF]
* [HIDE] - не показывать сообщения пользователю о процессе генерации
* [PRINT] или [PRINT=имя_принтера] - для печати отчета без просмотра. После знака равенства можно задать целевой принтер.
* [COPIES=*] для печати * копий отчета.
* [PAGES=1,2,5-8] для печати заданных страниц | [PAGES=BOOK] для формирования книжки | [PAGES=SIDE] - для печати четных и нечетных страниц
* [FORMAT] - Обновление оглавления, если оно есть (только если установлен MS Office)
* [ENCODE=N] - Позволяет записывать все данные отчета в перекодированном виде. Варианты N см. в параметрах ф-и STRCONV()
* [EXCEL] - Не зависимо от настроек POINT() для числовых полей в качестве разделителей ставит запятые.
*--------------------------------------------------------------------------------------------
* Ver 1.0 - 2010 г.
*--------------------------------------------------------------------------------------------
* Генератор предназначен для получения RTF отчетов без использования WORD а также текстовых
* отчетов с заданной структурой (например, XML или HTML). Имеет гибкую структуру,
* позволяющую последовательно добавлять неограниченное количество таблиц. Также можно вложить таблицу
* в контейнер и размножить ее по количеству записей в таблице контейнера. Скорость генерации - 5-50
* листов в секунду.
*
* Подключать необходимо либо по SET PROC, либо выполнять как DO - см. приложенную форму.
*
* @ Разработчик: TAS - Тимошенко Аскольд Сергеевич
* С вопросами и предложениями обращаться на E-Mail: [email protected]
* Данное решение находится на сайте http://www.foxclub.ru/sol/solution666.php в разделе решения с наименованием: Advanced RTF Report
*--------------------------------------------------------------------------------------------
* Ver 1.1 - 2010 г.
*--------------------------------------------------------------------------------------------
* 1. ADD: Добавлена возможность обратной сортировки, для этого конструкцию "ORD=выражение" писать
* как "ORD=DESC:выражение"
* 2. ADD: Добавлен показ % выполнения формирования разделов отчета
* 3. ADD: Добавлена возможность замены русских букв на HEX-коды при обработке символьных переменных
*--------------------------------------------------------------------------------------------
* Ver 1.2 - 2010 г.
*--------------------------------------------------------------------------------------------
* 1. ADD: Добавлены теги CASE, OTHERWISE, ENDCASE
* 2. ADD: Добавлен предварительный подсчет кол-ва разделов и вывод в градуснике "*** из ***"
* 3. IZM: Изменен метод запуска готового файла на WScript
*--------------------------------------------------------------------------------------------
* Ver 1.3 - 2010 г.
*--------------------------------------------------------------------------------------------
* 1. ADD: Добавлена возможность вывода в отчет PNG файлов (конструкция IMG: в описании символьных переменных)
* 2. ADD: Для картинок (переменных с IMG:) можно задавать 3 типа рамки: RM1-простая рамка,RM2-рамка
* с тенью,RM3-двойная рамка
* 3. ADD: Добавлена возможность разделения разрядов при обработке числовых переменных (конструкция RAZ:)
* 4. ADD: Добавлен вывод ДА/НЕТ при обработке логических переменных (конструкция LRU:)
*--------------------------------------------------------------------------------------------
* Ver 1.4 - 2010 г.
*--------------------------------------------------------------------------------------------
* 1. ERR: Исправлена неадекватная работа счетчика str_tbl (не сбрасывался на 0 при смене таблицы)
* 2. ERR: Исправлен рабочий алиас заголовка и подвала контейнера (переменные не отрабатывались
* правильно без явного указания алиаса контейнера)
* 3. ADD: Добавлена возможность задавать условие в теге [ALI] как USL$выражение для поиска по списку.
* Условием для добавления записей в таблицу, находящуюся в группе, в этом случае является:
* выражение IN (ключ), т.е. ключ должен быть вида "1,2,3" или "'AA','BB','CC'".
*--------------------------------------------------------------------------------------------
* Ver 1.5 - 2010 г.
*--------------------------------------------------------------------------------------------
* 1. ADD: Добавлена возможность задавать подстановки для переменных (конструкция REPVAR*:) Потом доступно
* использование в переменных вида [&*], где * - ID подстановки). Переменная наследует все функции
* подстановки, при этом функции переменной приоритетней функций подстановки.
* 2. IZM Ранее переменные переводились UPPER() теперь этого не делается. Это сделано для того, чтобы переменные вида
* ["Дата:"+DTOC(DATE())] выводились в виде "Дата:..." а не "ДАТА:...". Индексы, условия,
* группировки и сортировки остались регистронезависимыми (переводятся в UPPER() перед обработкой)!
*--------------------------------------------------------------------------------------------
* Ver 1.6 - 2010 г.
*--------------------------------------------------------------------------------------------
* 1. ADD: Добавлен параметр [ADDF] в конфигурации запуска для подавления ошибки создания выходного файла. В случае,
* если файл результата не может быть перезаписан, добавляет к имени файла "_N", где N может быть от 1 до 49 и
* пытается записать с новым именем. При достижении N=50, формирует ошибку доступа к диску.
* 2. ADD: Добавлена возможность вывода в отчет JPG файлов.
*--------------------------------------------------------------------------------------------
* Ver 2.0 - 2010 г.
*--------------------------------------------------------------------------------------------
* ВНИМАНИЕ! VER 2.0 НЕСОВМЕСТИМА С ПРЕДЫДУЩИМИ ВЕРСИЯМИ В ПЛАНЕ СЧЕТЧИКОВ И АЛИАСОВ ГРУПП!!!
*--------------------------------------------------------------------------------------------
* 1. ADD: Добавлена возможность добавлять подгруппы. Подгруппы объявляются также как и группы.
* МАХ вложенность групп=6.
* 2. IZM: Полностью изменен подход к счетчикам, теперь их стало 72 штуки.
* 3. IZM: Алиас группы изменился с GRP на GR1,GR2,GR3... - в зависимости от вложенности
*--------------------------------------------------------------------------------------------
* Ver 2.1 - 2010 г.
*--------------------------------------------------------------------------------------------
* 1. ERR: Поправлен счетчик [tbl_str] (в некоторых случаях считал неверно)
* 2. ERR: Исправлена ошибка обработки файлов у которых внутренние шрифты указаны без кодировки.
* 3. ADD: Добавлена функция форматирования "BLZ" - выводит число 1000000 как 1 000 000, разделяя разряды пробелами,
* при этом если число=0, то не выводит ничего.
* 4. ADD: Добавлена функция форматирования "BLK" - если число=0, то не выводит ничего.
* 5. ADD: Добавлен параметр [HIDE] в конфигурации запуска для подавления сообщений процесса генерации
*--------------------------------------------------------------------------------------------
* Ver 2.2 - 2010 г.
*--------------------------------------------------------------------------------------------
* 1. ERR: Поправлены косяки с подстановками в переменных. (Для ряда функций брались не те данные)
* 2. ADD: В целях унификации шаблонов добавлена подстановка "&" при описании контейнеров, таблиц или групп.
* Пример использования [REP:ALI=&myalias|ORD=&myorder] - здесь в "ALI=&myalias" - "&" - признак подстановки,
* "myalias" - переменная, которая содержит значения алиаса. Так же и для сортировки.
* Переменные "myalias" и "myorder" должны быть описаны до запуска генератора!
* Подстановка может быть использована для любой секции и позволит многократно использовать один и
* тот же шаблон для схожих по структуре данных.
* 3. ADD: Добавлена функция преобразования "RD3" - округление до 3 знаков после запятой.
* 4. ADD: Добавлена пользовательская функция форматирования переменных: конструкция "FUN=USERFUNC" или
* "FUN=USERFUNC(m.znh_now)". Если нужно в вашу функцию передать более одного значения, то для передачи
* текущего значения поля нужно пользоваться переменной m.znh_now.Если параметр только один, то задавать
* его не нужно - будет автоматически добавлено к имени функции концовка "(m.znh_now)"!
* Эта конструкция разделяется двоеточием от остальных функций. Выполняется после всех преобразований,
* при этом имейте ввиду, что тип переменной m.znh_now в момент запуска пользовательской функции, всегда
* символьный! На выходе также ожидается значение символьного типа!
*--------------------------------------------------------------------------------------------
* Ver 2.3 - 2010 г.
*--------------------------------------------------------------------------------------------
* 1. ERR: Поправлен подвал группировок и ссылки на другие группы. (Теперь в алиасе, на который ссылается
* переменная, указатель записи из EOF() переводится на BOTTOM).
* 2. ERR: Исправлена ошибка с ограничением до 3, распознавания секций в описании переменных. В связи с этим
* часть ф-й могли не распознаться. (Теперь увеличено до 10)
* 3. IZM: Теперь концовка к имени пользовательской функции форматирования переменных добавляется не "(m.znh_now)"
* a "(m.znh_val)". Проверьте свои шаблоны!
* 4. ADD: Добавлена переменная ZNH_VAL с вычисленным, но не преобразованным значением для использования во внешних
* функциях. Тип переменной ZNH_VAL тот, который имеет поле (выражение) в источнике.
* ВНИМАНИЕ! Если вы используете внешнюю функцию с переменной ZNH_VAL, то функции преобразования и
* форматирования задавать бессмысленно!
* 5. ADD: Добавлена переменная ZNH_CON с вычисленным и преобразованным но не отформатированным значением
* для использования во внешних функциях. Тип переменной ZNH_CON тот, который имеет который имеет
* функция преобразования на выходе.
* ВНИМАНИЕ! Если вы используете внешнюю функцию с переменной ZNH_CON, то функции форматирования
* задавать бессмысленно!
*--------------------------------------------------------------------------------------------
* Ver 2.4 - 2010 г.
*--------------------------------------------------------------------------------------------
* 1. ERR: Исправлена ошибка с длинными путями при показе готового отчета (теперь полное имя файла оборачивается в кавычки)
* 2. ADD: Добавлен параметр [PRINT] или [PRINT=имя_принтера] в конфигурации запуска для печати отчета без просмотра.
* После знака равенства можно задать целевой принтер.
* 3. ADD: Добавлен параметр [COPIES=*] для печати * копий отчета. Актуально только совместно с [PRINT]
* 4. ADD: Добавлен параметр [PAGES=1,2,5-8] для печати заданных страниц | [PAGES=BOOK] для формирования книжки | [PAGES=SIDE] - для печати четных и нечетных страниц
* Актуально только совместно с [PRINT]
*--------------------------------------------------------------------------------------------
* Ver 2.5 - 2011 г.
*--------------------------------------------------------------------------------------------
* 1. ADD: Добавлен параметр [MERGE] - Позволяет объединять текущий результат с существующим файлом WORD.
* 2. IZM: Тег [ENDPAGE] теперь не срабатывает на последних записях текущей таблицы
* 3. ADD: У тега [ENDPAGE] добавлена возможность задавать условие срабатывания: конструкция USL=выражение (задается через разделитель "|")
* 4. ADD: Добавлена пост обработка полученного файла (параметр [FORMAT]): обновление оглавления, если оно есть (только если установлен MS Office)
* 5. IZM: Оптимизация ввода/вывода. Существенное ускорение разборки шаблонов отчетов.
* 6. ADD: Добавлена функция форматирования "TDT" – преобразует DATETIME значение в тип DATE.
* 7. ERR: Исправлена ошибка исполнения условий объектов в безалиасной зоне.
*--------------------------------------------------------------------------------------------
* Ver 2.6 - 2013 г.
*--------------------------------------------------------------------------------------------
* Добавлена функция SPLIT_REPORT(), надстройка над RTF_REPORT() - дает возможность разделения отчета на несколько файлов. Здесь и далее будут
* использоваться ссылки, для привязки изменений к конкретной функции.
* [1] - изменения для функции RTF_REPORT()
* [2] - изменения для функции SPLIT_REPORT()
*--------------------------------------------------------------------------------------------
* 1. [1].ADD: Генератор можно использовать для формирования текстовых (HTML и XML) отчетов.
* 2. [1].ERR: Исправлена ошибка применения условия таблицы, заданной вне контейнера
* 3. [1].ADD: Добавлен параметр [COD=N] - Позволяет записывать данные поля в перекодированном виде. Варианты N см. в параметрах ф-и STRCONV()
* Параметр [COD] имеет более высокий приоритет, чем параметр [ENCODE].
* 4. [1].ADD: Добавлен параметр [ENCODE=N] - Позволяет записывать все данные отчета в перекодированном виде. Варианты N см. в параметрах ф-и STRCONV()
* (Например, есть шаблон в кодировке 1251, необходимо сохранить XML файл в кодировке utf-8).
* 5. [2].ADD: Добавлена функция SPLIT_REPORT(), надстройка над RTF_REPORT() - дает возможность разделения отчета на несколько файлов.
* 6. [2].ADD: Добавлен ОБЯЗАТЕЛЬНЫЙ параметр [SPLIT=*] - где "*" - MAX количество записей в томе.
* 7. [2].ADD: Добавлен параметр [STOMS=1,2,5-8] для формирования только указанных томов.
*--------------------------------------------------------------------------------------------
* Ver 2.7 - 2015 г.
*--------------------------------------------------------------------------------------------
* 1. [1].ADD: Добавлена функция преобразования "PAR" - для добавления текста содержащего несколько строк в виде отдельных параграфов. Актуально только для RTF файла.
*--------------------------------------------------------------------------------------------
* Ver 2.8 - 2018 г.
*--------------------------------------------------------------------------------------------
* 1. [1].ERR: Добавлена проверка длины наименования функции преобразования, чтобы исключить их срабатывание при похожем начале имени переменной и установкой SET EXACT OFF.
* 2. [1].ADD: Добавлена функция преобразования "ML5" - масштабирование (уменьшение) картинки на 50% (актуально только для конструкции "IMG").
*--------------------------------------------------------------------------------------------
* Ver 2.9 - 2018 г.
*--------------------------------------------------------------------------------------------
* 1. [1].IZM: Более чем в 2 раза ускорена функция разборки шаблона READ_RTF().
*--------------------------------------------------------------------------------------------
* Ver 3.0 - 2019 г.
*--------------------------------------------------------------------------------------------
* Добавлена функция XLS_REPORT, надстройка над RTF_REPORT() для формирования отчетов в EXCEL с использованием XML шаблонов.
* Добавлена функция DBF_TOEXCEL - продвинутая выгрузка данных курсора в EXCEL. Может использоваться отдельно.
* [1] - изменения для функции RTF_REPORT()
* [2] - изменения для функции SPLIT_REPORT()
* [3] - изменения для функции XLS_REPORT()
* [4] - изменения для функции DBF_TOEXCEL()
*--------------------------------------------------------------------------------------------
* 1. [1].ADD: Добавлена поддержка выгрузки в EXCEL.
* 2. [3].ADD: Добавлена функции XLS_REPORT().
* 3. [4].ADD: Добавлена функции DBF_TOEXCEL().
*--------------------------------------------------------------------------------------------
* Ver 3.1 - 2019 г.
*--------------------------------------------------------------------------------------------
* 1. [1].IZM: Добавлена функция преобразования "NUM" - для приведения типа ячейки к числовому формату (актуально только для формирования отчетов в EXCEL).
*--------------------------------------------------------------------------------------------
* Ver 3.2 - 2019 г.
*--------------------------------------------------------------------------------------------
* 1. [1].IZM: Функция ENCODE_SYMBOLS переписана для более быстрого выполнения.
* 2. [3].ADD: Добавлен тег «[REP:NOTE]» для добавления в шаблон строк с комментариями (актуален только для шаблонов EXCEL). В готовый отчет эти строки добавлены не будут.
*--------------------------------------------------------------------------------------------
* Ver 3.3 - 2019 г.
*--------------------------------------------------------------------------------------------
* 1. [1].IZM: Добавлена возможность вывода в WORD отчет PNG графиков (нужен EXCEL!!!, конструкция DIA: GEN_DIAGR() - см. пример для WORD № 12)
* 2. [3].IZM: Добавлен 4-й параметр для конвертации результата в большое кол-во форматов. Теперь по умолчанию результат остается в XML виде.
* 3. [3].IZM: Изменен подход к шаблонам с выделенной служебной колонки на служебные строки (см. примеры EXCEL).
*--------------------------------------------------------------------------------------------
IF VARTYPE(m.rep_config)#"C"
rep_config=''
ENDIF
f_shabl = ALLTRIM(m.f_shabl)
LOCAL i,form_ret,file_nom,file_name,f_printer,f_pcopies,f_conftxt,openword,loWord,file_id
PRIVATE f_out,rep_errs,proc_all,proc_now,proc_kol,proc_rzd,proc_lvl,proc_glv,alias_in,reps_cod
rep_errs='' && переменная для ошибки
proc_all=0 && всего шагов для текущего proc_rzd
proc_now=0 && текущий шаг
proc_kol=0 && кол-во %
proc_rzd=0 && раздел
proc_lvl=0 && уровень 1-контейнер, 2-группа, 3-строка
reps_cod=0 && перекодировка файла
alias_in=ALIAS() && текущий алиас
FOR i=1 TO GETWORDCOUNT(m.rep_config,"]")
f_conftxt=ALLTRIM(GETWORDNUM(m.rep_config,m.i,"]"))
DO CASE
CASE ALLTRIM(UPPER(LEFT(m.f_conftxt,8)))=="[ENCODE="
reps_cod=VAL(SUBSTR(m.f_conftxt,AT("=",m.f_conftxt)+1))
reps_cod=IIF(BETWEEN(m.reps_cod,1,16),m.reps_cod,0)
ENDCASE
ENDFOR
*--------------------------------------------------------------------------------------------
* загрузка структуры
*--------------------------------------------------------------------------------------------
WAIT WINDOW IIF("[HIDE]"$UPPER(m.rep_config),"","Идет загрузка структуры") NOWAIT NOCLEAR
*aaa=SECONDS()
form_ret=READ_RTF(m.f_shabl) && формирование струтуры
*WAIT WINDOW STR(SECONDS()-aaa,10,2)
*--------------------------------------------------------------------------------------------
* генерация отчета
*--------------------------------------------------------------------------------------------
file_nom=0 && для № файла
file_name=m.f_othet && запоминается оригинальное имя файла
IF m.form_ret=1
proc_glv=GET_RAZDKOL() && получение количества независимых разделов в шаблоне
DO WHILE .T.
IF "[MERGE]"$UPPER(m.rep_config) AND FILE(m.f_othet)
rep_config=STRTRAN(m.rep_config,"[ADDF]","")
m.f_othet=SYS(2023)+"\"+SYS(2015)+".rtf" && временное имя файла
ENDIF
f_out = FCREATE(m.f_othet)
DO CASE
CASE m.f_out<0 AND "[ADDF]"$UPPER(m.rep_config)
IF m.file_nom<50
file_nom=m.file_nom+1
f_othet=ADDBS(JUSTPATH(m.file_name))+JUSTSTEM(m.file_name)+"_"+ALLTRIM(STR(m.file_nom))+"."+JUSTEXT(m.file_name)
ELSE
rep_errs='Ошибка создания выходного файла! Проверьте наличие доступа к папке: '+ADDBS(JUSTPATH(m.file_name))
form_ret=-1
EXIT
ENDIF
CASE m.f_out<0
rep_errs='Ошибка создания выходного файла! Возможно этот файл открыт в WORD?'
form_ret=-1
EXIT
OTHERWISE
form_ret=ADD_REP() && формирование тела файла
=FCLOSE(m.f_out)
EXIT
ENDCASE
ENDDO
ENDIF
*--------------------------------------------------------------------------------------------
* объединение полученного результата с существующим файлом по опции [MERGE]
*--------------------------------------------------------------------------------------------
IF m.form_ret=1 AND "[MERGE]"$UPPER(m.rep_config) AND FILE(m.f_othet)
WAIT WINDOW IIF("[HIDE]"$UPPER(m.rep_config),"","Идет объединение файлов...") NOWAIT NOCLEAR
openword=0
file_id=FOPEN(m.file_name,12)
IF m.file_id<=0 && файл не удалось открыть на запись
form_ret=-1
rep_errs='Ошибка объединения полученного результата с существующим файлом! Возможно этот файл открыт в WORD?'
ELSE
=FCLOSE(m.file_id)
TRY
loWord=CREATEOBJECT('Word.Application')
loWord.Visible=.F.
openword=1 && добрались до этой строки - значит будем закрывать WORD при завершении
loBook = loWord.Documents.open(FULLPATH(m.file_name))
loWord.ActiveDocument.Range.Select
loWord.Selection.EndKey(6)
loWord.Selection.TypeParagraph && добавляем новый параграф с очищенным форматированием
loWord.Selection.ClearFormatting
loWord.Selection.InsertBreak(2)
loWord.Selection.InsertFile(FULLPATH(m.f_othet))
loWord.Selection.HomeKey(6)
loWord.DisplayAlerts = 0
loWord.ActiveDocument.Save()
loWord.Quit(0)
LoWord=.NULL.
DELETE FILE (m.f_othet) && удаляем временный файл
f_othet=m.file_name
CATCH TO goto_error
rep_errs='Ошибка объединения полученного результата с существующим файлом! Возможно этот файл открыт в WORD?'
form_ret=-1
IF m.openword=1
LoWord.Quit(0)
LoWord=.NULL.
ENDIF
ENDTRY
ENDIF
ENDIF
*--------------------------------------------------------------------------------------------
* Обновление оглавления (если есть)
*--------------------------------------------------------------------------------------------
IF m.form_ret=1 AND "[FORMAT]"$UPPER(m.rep_config)
WAIT WINDOW IIF("[HIDE]"$UPPER(m.rep_config),"","Идет форматирование...") NOWAIT NOCLEAR
TRY
openword=0
loWord=CREATEOBJECT('Word.Application')
loWord.Visible=.f.
openword=1 && добрались до этой строки - значит будем закрывать WORD при завершении
loBook = m.loWord.Documents.Open(FULLPATH(m.file_name))
IF loBook.TablesOfContents.Count>0 && если есть оглавление
loBook.TablesOfContents.Item(1).Update && то обновляем его
ENDIF
loWord.DisplayAlerts = 0
loWord.ActiveDocument.Save()
CATCH TO goto_error
ENDTRY
IF m.openword=1
LoWord.Quit(0)
LoWord=.NULL.
ENDIF
ENDIF
IF "[HIDE]"$UPPER(m.rep_config)=.F.
WAIT CLEAR
ENDIF
*--------------------------------------------------------------------------------------------
* запуск просмотра готового файла
*--------------------------------------------------------------------------------------------
IF m.form_ret=1
DO CASE
CASE "[SHOW]"$UPPER(m.rep_config) && Показать отчет
WSHShell=CreateObject("WScript.Shell",0,.F.)
WSHShell.Run('"'+m.f_othet+'"')
CASE "[PRINT"$UPPER(m.rep_config) && Печать
f_printer=''
f_pcopies=1
f_pages=''
FOR i=1 TO GETWORDCOUNT(m.rep_config,"]")
f_conftxt=ALLTRIM(GETWORDNUM(m.rep_config,m.i,"]"))
DO CASE
CASE ALLTRIM(UPPER(LEFT(m.f_conftxt,7)))=="[PRINT="
f_printer=ALLTRIM(SUBSTR(m.f_conftxt,AT("=",m.f_conftxt)+1))
CASE ALLTRIM(UPPER(LEFT(m.f_conftxt,8)))=="[COPIES="
f_pcopies=VAL(SUBSTR(m.f_conftxt,AT("=",m.f_conftxt)+1))
CASE ALLTRIM(UPPER(LEFT(m.f_conftxt,7)))=="[PAGES="
f_pages=SUBSTR(m.f_conftxt,AT("=",m.f_conftxt)+1)
ENDCASE
ENDFOR
WAIT WINDOW IIF("[HIDE]"$UPPER(m.rep_config),"","Идет печать документа...") NOWAIT NOCLEAR
IF PrintAny(m.f_othet,m.f_printer,m.f_pcopies,m.f_pages)<=0
rep_errs='Ошибка при печати WORD документа!'
ENDIF
IF "[HIDE]"$UPPER(m.rep_config)=.F.
WAIT CLEAR
ENDIF
ENDCASE
ENDIF
*--------------------------------------------------------------------------------------------
IF USED("_rtfreport")
USE IN _rtfreport
ENDIF
IF USED("_rtftables")
USE IN _rtftables
ENDIF
IF USED("_rtfvables")
USE IN _rtfvables
ENDIF
IF !EMPTY(m.alias_in) AND USED(m.alias_in)
SELECT (m.alias_in)
ENDIF
RETURN m.rep_errs && пустая, если все ОК!
*############################################################################################
*############################################################################################
*############################################################################################
FUNCTION ADD_REP && головная ф-я формирования выходного файла
LOCAL rep_okey,tbl_alia
*--------------------------------------------------------------------------------------------
* Переменные для счетчиков
*--------------------------------------------------------------------------------------------
DIMENSION rep_shet(72) && массив счетчиков
PRIVATE rep_con,rep_tbl,rep_gr1,rep_gr2,rep_gr3,rep_gr4,rep_gr5,rep_gr6,rep_str
PRIVATE con_all,con_now,con_str,con_tbl,con_gr1,con_gr2,con_gr3,con_gr4,con_gr5,con_gr6
PRIVATE tbl_all,tbl_now,tbl_str,tbl_gr1,tbl_gr2,tbl_gr3,tbl_gr4,tbl_gr5,tbl_gr6,tbl_kol
PRIVATE gr1_all,gr1_now,gr1_str,gr1_gr2,gr1_gr3,gr1_gr4,gr1_gr5,gr1_gr6,gr1_kol,gr1_tek
PRIVATE gr2_all,gr2_now,gr2_str,gr2_gr3,gr2_gr4,gr2_gr5,gr2_gr6,gr2_kol,gr2_tek
PRIVATE gr3_all,gr3_now,gr3_str,gr3_gr4,gr3_gr5,gr3_gr6,gr3_kol,gr3_tek
PRIVATE gr4_all,gr4_now,gr4_str,gr4_gr5,gr4_gr6,gr4_kol,gr4_tek
PRIVATE gr5_all,gr5_now,gr5_str,gr5_gr6,gr5_kol,gr5_tek
PRIVATE gr6_all,gr6_now,gr6_tek
rep_shet=0 && обнуление массива счетчиков
STORE 0 TO rep_con,rep_tbl,rep_gr1,rep_gr2,rep_gr3,rep_gr4,rep_gr5,rep_gr6,rep_str
STORE 0 TO con_all,con_now,con_str,con_tbl,con_gr1,con_gr2,con_gr3,con_gr4,con_gr5,con_gr6
STORE 0 TO tbl_all,tbl_now,tbl_str,tbl_gr1,tbl_gr2,tbl_gr3,tbl_gr4,tbl_gr5,tbl_gr6,tbl_kol
STORE 0 TO gr1_all,gr1_now,gr1_str,gr1_gr2,gr1_gr3,gr1_gr4,gr1_gr5,gr1_gr6,gr1_kol,gr1_tek
STORE 0 TO gr2_all,gr2_now,gr2_str,gr2_gr3,gr2_gr4,gr2_gr5,gr2_gr6,gr2_kol,gr2_tek
STORE 0 TO gr3_all,gr3_now,gr3_str,gr3_gr4,gr3_gr5,gr3_gr6,gr3_kol,gr3_tek
STORE 0 TO gr4_all,gr4_now,gr4_str,gr4_gr5,gr4_gr6,gr4_kol,gr4_tek
STORE 0 TO gr5_all,gr5_now,gr5_str,gr5_gr6,gr5_kol,gr5_tek
STORE 0 TO gr6_all,gr6_now,gr6_tek
*--------------------------------------------------------------------------------------------
rep_okey=1
tbl_alia=GET_REPALIAS("[REP]")
SELECT * FROM _rtfreport WHERE !INLIST(obtype,3,4,5,6,9,12,13,14,15) AND EMPTY(rodrid) INTO CURSOR (m.tbl_alia) READWRITE
SCAN && 1 раз по каждому разделу верхнего уровня кроме группировок и детайл
proc_lvl=0 && сброс уровня отображения % в начале каждого раздела
DO CASE
CASE obtype=2
rep_okey=ADD_TBL(rnomer,tnomer,grnext,grpend) && отвечает также за добавление 3,4,5,6
CASE obtype=10
rep_okey=ADD_CON(rnomer,tnomer,rid) && отвечает также за добавление всего, что внутри для текущего RID
OTHERWISE
rep_okey=ADD_STR(rnomer,rztype,IIF(SEEK(tnomer,"_rtftables","k1"),ALLTRIM(_rtftables.ALINOW),m.alias_in))
ENDCASE
IF m.rep_okey<=0
EXIT
ENDIF
ENDSCAN
USE IN (m.tbl_alia)
RETURN m.rep_okey
*############################################################################################
*############################################################################################
*############################################################################################
FUNCTION GET_RAZDKOL && получение количества независимых разделов в шаблоне
LOCAL razd_kol,razd_con
razd_kol=0
razd_con=0
SELECT _rtfreport
SCAN FOR INLIST(obtype,2,10,11) && контейнеры и таблицы
razd_con=ICASE(obtype=10,1,obtype=11,0,m.razd_con)
DO CASE
CASE obtype=10 && начинается контейнер
razd_kol=m.razd_kol+1
CASE obtype=2 AND m.razd_con=0 && начинается таблица, при условии, что она не в контейнере
razd_kol=m.razd_kol+1
ENDCASE
ENDSCAN
RETURN m.razd_kol
*############################################################################################
*############################################################################################
*############################################################################################
FUNCTION ADD_CON && добавление контейнера
LPARAMETERS t_rnomer,t_anomer,t_rid
* t_rnomer - номер раздела
* t_anomer - номер алиаса
* t_rid - ID раздела текущего контейнера
*--------------------------------------------------------------------------------------------
LOCAL tbl__ali,tbl__key,ali_now,tbl__ord,tbl__des,rep_okey,key_data,ali_con
=SEEK(m.t_anomer,"_rtftables","k1")
tbl__ali=ALLTRIM(_rtftables.ALINOW)
tbl__key=ALLTRIM(_rtftables.ALIKEY)
tbl__ord=ALLTRIM(_rtftables.ALIORD)
tbl__des=_rtftables.ALIDES
ali_now=GET_REPALIAS("[CON]") && алиас с данными по контейнеру для цикла
ali_con=GET_REPALIAS("[RZD]") && алиас с разделами для обработки
tbl__key=IIF(EMPTY(m.tbl__key),"1=1",GET_FUNCONV(m.tbl__key))
tbl__ord=IIF(EMPTY(m.tbl__ord),"1",m.tbl__ord)
*--------------------------------------------------------------------------------------------
TEXT TO tempusl NOSHOW TEXTMERGE PRETEXT 7
SELECT <<m.tbl__ord>> AS order_fld,* ;
FROM <<m.tbl__ali>> ;
ORDER BY 1 <<IIF(m.tbl__des=1,"DESC","")>> ;
INTO CURSOR <<m.ali_now>> READWRITE
ENDTEXT
rep_okey=1
TRY
=EXECSCRIPT(m.tempusl)
CATCH
rep_okey=0
rep_errs='Не удалось получить данные для отчета!'
ENDTRY
IF m.rep_okey=1
=RUN_SHET(1,0) && инициализация счетчиков по контейнеру
SELECT * FROM _rtfreport WHERE rodrid=m.t_rid AND INLIST(obtype,2,7) INTO CURSOR (m.ali_con) READWRITE
*--------------------------------------------------------------------------------------------
* Формирование % выполнения
*--------------------------------------------------------------------------------------------
proc_lvl=1 && уровень 1-контейнер, 2-группа, 3-строка
proc_all=con_all && всего шагов для текущего proc_rzd
proc_now=0 && текущий шаг %
proc_kol=0 && кол-во %
proc_rzd=m.proc_rzd+1 && раздел
SELECT (m.ali_now)
SCAN
=RUN_SHET(1,1) && отработка счетчиков по контейнеру
proc_now=m.proc_now+1 && текущий шаг %
=SHOW_PROC() && показ % выполнения
*--------------------------------------------------------------------------------------------
* Формирование заголовка контейнера
*--------------------------------------------------------------------------------------------
IF m.rep_okey=1
rep_okey=ADD_STR(m.t_rnomer,10,m.ali_now)
ENDIF
*--------------------------------------------------------------------------------------------
SELECT (m.ali_now)
TRY
key_data=EVALUATE(m.tbl__key) && ключевое значение для выборки данных из таблицы
CATCH
rep_okey=0
rep_errs='Неверно задано ключевое выражение при описании контейнера!'
ENDTRY
IF m.rep_okey=1
SELECT (m.ali_con) && верхний уровень в контейнере - начало и конец таблиц
SCAN
DO CASE
CASE obtype=2
rep_okey=ADD_TBL(rnomer,tnomer,grnext,grpend,m.key_data,m.ali_now) && отвечает также за добавление 3,4,5,6
OTHERWISE
rep_okey=ADD_STR(rnomer,rztype,m.ali_now)
ENDCASE
IF m.rep_okey<=0
EXIT
ENDIF
ENDSCAN
ENDIF
IF rep_okey#1
EXIT
ENDIF
ENDSCAN
ENDIF
*--------------------------------------------------------------------------------------------
IF USED(m.ali_con)
USE IN (m.ali_con)
ENDIF
IF USED(m.ali_now)
USE IN (m.ali_now)
ENDIF
RETURN m.rep_okey
*############################################################################################
*############################################################################################
*############################################################################################
FUNCTION ADD_TBL && добавление таблицы
LPARAMETERS t_rnomer,t_anomer,t_grnext,t_tblend,t_keydata,t_keyalia
* t_rnomer - номер раздела
* t_anomer - номер алиаса
* t_grnext - номер раздела группы таблицы
* t_tblend - номер раздела подвала таблицы
* t_keydata - ключевое значение для выборки данных из таблицы
* t_keyalia - алиас с данными для получения значения ключа
*--------------------------------------------------------------------------------------------
LOCAL rep_okey,tbl__ali,ali__grp,ali__now,tbl__add,ali__dat,tbl__dtl,grp_head
=SEEK(m.t_anomer,"_rtftables","k1")
tbl__ali=ALLTRIM(_rtftables.ALINOW)
ali__now=GET_REPALIAS("[TBL]")
ali__grp=GET_REPALIAS("[GZ1]")
ali__dat=GET_REPALIAS("[GR1]")
tbl__add=_rtftables.ALIADD
*--------------------------------------------------------------------------------------------
* Получение курсоров данных таблицы и заголовков групп
*--------------------------------------------------------------------------------------------
rep_okey=GET_TBLDATA(m.t_anomer,m.t_keydata,m.t_keyalia)
*--------------------------------------------------------------------------------------------
* Формирование заголовка таблицы
*--------------------------------------------------------------------------------------------
IF m.rep_okey=1
=RUN_SHET(2,0) && инициализация счетчиков по таблице
=RUN_SHET(2,1) && отработка счетчиков по таблице
IF m.tbl_all>0 OR m.tbl__add=1 && если есть хоть 1 запись или указано выдавать и пустую
rep_okey=ADD_STR(m.t_rnomer,2,m.tbl__ali) && заголовок таблицы
IF m.rep_okey=1
IF SEEK(STR(m.t_anomer,10)+STR(4,2),"_rtfreport","k3") && ищем раздел для detail этой таблицы
tbl__dtl=_rtfreport.rnomer && раздел detail
ENDIF
IF m.t_grnext>0 && есть группы у этой таблицы
rep_okey=GET_GRPTITL(m.t_anomer,1) && курсор с заголовками для группы 1 уровня
*--------------------------------------------------------------------------------------------
* Формирование % выполнения
*--------------------------------------------------------------------------------------------
IF m.rep_okey=1
IF INLIST(m.proc_lvl,0,2) AND RECCOUNT(m.ali__grp)>1 && всего групп у таблицы>1
proc_lvl=2 && уровень 1-контейнер, 2-группа, 3-строка
proc_all=RECCOUNT(m.ali__grp) && всего шагов для текущего proc_rzd
proc_now=0 && текущий шаг %
proc_kol=0 && кол-во %
proc_rzd=m.proc_rzd+1 && раздел
ENDIF
*--------------------------------------------------------------------------------------------
* Формирование групп таблицы
*--------------------------------------------------------------------------------------------
=RUN_SHET(3,0) && инициализация счетчиков по группе 1 уровня
SELECT (m.ali__grp)
SCAN
rep_okey=GET_GRPDATA(m.t_anomer,1,grp_dat) && курсор с данными для группы 1 уровня
IF m.rep_okey=1
=RUN_SHET(3,1) && отработка счетчиков по группе 1 уровня
DO CASE
CASE m.proc_lvl=2
proc_now=m.proc_now+1 && текущий шаг %
=SHOW_PROC() && показ % выполнения
CASE INLIST(m.proc_lvl,0,3)
proc_lvl=3 && уровень 1-контейнер, 2-группа, 3-строка
proc_all=RECCOUNT(m.ali__now) && всего шагов для текущего proc_rzd
proc_now=0 && текущий шаг %
proc_kol=0 && кол-во %
proc_rzd=m.proc_rzd+1 && раздел
ENDCASE
rep_okey=ADD_GRP(m.t_anomer,1,m.ali__dat,m.t_grnext,m.tbl__dtl) && для каждой группы по текущей таблице
ENDIF
IF m.rep_okey#1
EXIT
ENDIF
ENDSCAN
ENDIF
*--------------------------------------------------------------------------------------------
* Формирование строчек таблицы
*--------------------------------------------------------------------------------------------
ELSE
IF INLIST(m.proc_lvl,0,3)
proc_lvl=3 && уровень 1-контейнер, 2-группа, 3-строка
proc_all=RECCOUNT(m.ali__now) && всего шагов для текущего proc_rzd
proc_now=0 && текущий шаг %
proc_kol=0 && кол-во %
proc_rzd=m.proc_rzd+1 && раздел
ENDIF
rep_okey=ADD_STRALIA(m.ali__now,m.tbl__dtl)
ENDIF
ENDIF
*--------------------------------------------------------------------------------------------
* Формирование подвала таблицы
*--------------------------------------------------------------------------------------------
IF m.rep_okey=1 AND !EMPTY(m.t_tblend)
rep_okey=ADD_STR(m.t_tblend,6,m.tbl__ali)
ENDIF
ENDIF
ENDIF
*--------------------------------------------------------------------------------------------
IF USED(m.ali__dat)
USE IN (m.ali__dat)
ENDIF
IF USED(m.ali__grp)
USE IN (m.ali__grp)
ENDIF
IF USED(m.ali__now)
USE IN (m.ali__now)
ENDIF
RETURN m.rep_okey
*############################################################################################
*############################################################################################
*############################################################################################
FUNCTION ADD_GRP && добавление группы
LPARAMETERS t_anomer,grp_level,grp_alias,grp_head,tbl__dtl
* t_anomer - номер алиаса
* grp_level - уровень вложенности
* grp_alias - алиас с данными
* grp_head - номер раздела головы группы
* tbl__dtl - номер раздела DETAIL таблицы
*--------------------------------------------------------------------------------------------
LOCAL rep_okey,ali__dat,grp__ttl,grp__end,grp__nxt
ali__dat=GET_REPALIAS("[GR"+ALLTRIM(STR(m.grp_level+1))+"]")
grp__ttl=GET_REPALIAS("[GZ"+ALLTRIM(STR(m.grp_level+1))+"]")
*--------------------------------------------------------------------------------------------
* Формирование головы группы
*--------------------------------------------------------------------------------------------
=SEEK(m.grp_head,"_rtfreport","k5")
grp__end=_rtfreport.grpend && RID хвоста группы
grp__nxt=_rtfreport.grnext && RID подгруппы
rep_okey=ADD_STR(m.grp_head,3,m.grp_alias)
IF m.rep_okey=1
*--------------------------------------------------------------------------------------------
* Формирование подгрупп группы
*--------------------------------------------------------------------------------------------
IF m.grp__nxt>0 && есть подгруппы
rep_okey=GET_GRPTITL(m.t_anomer,m.grp_level+1) && курсор с заголовками для группы N+1 уровня
=RUN_SHET(3+m.grp_level,0) && инициализация счетчиков по группе N+1 уровня
SELECT (m.grp__ttl)
SCAN
rep_okey=GET_GRPDATA(m.t_anomer,m.grp_level+1,grp_dat) && курсор с данными для группы N+1 уровня
IF m.rep_okey=1
=RUN_SHET(3+m.grp_level,1) && отработка счетчиков по группе N+1 уровня
rep_okey=ADD_GRP(m.t_anomer,m.grp_level+1,m.ali__dat,m.grp__nxt,m.tbl__dtl) && для каждой группы по текущей таблице
ENDIF
IF m.rep_okey#1
EXIT
ENDIF
ENDSCAN
*--------------------------------------------------------------------------------------------
* Формирование строчек группы
*--------------------------------------------------------------------------------------------
ELSE
rep_okey=ADD_STRALIA(m.grp_alias,m.tbl__dtl)
ENDIF
ENDIF
*--------------------------------------------------------------------------------------------
* Формирование подвала группы
*--------------------------------------------------------------------------------------------
IF m.rep_okey=1 AND !EMPTY(m.grp__end)
rep_okey=ADD_STR(m.grp__end,3,m.grp_alias)
ENDIF
*--------------------------------------------------------------------------------------------
IF USED(m.ali__dat)
USE IN (m.ali__dat) && закрываем курсоры N+1 вложенности
ENDIF
IF USED(m.grp__ttl)
USE IN (m.grp__ttl) && закрываем курсоры N+1 вложенности
ENDIF
RETURN m.rep_okey
*############################################################################################
*############################################################################################
*############################################################################################
FUNCTION ADD_STRALIA && добавление объектов по всем строкам алиаса
LPARAMETERS tek_alias,tbl__dtl
SELECT (m.tek_alias)
SCAN
=RUN_SHET(9,1) && отработка счетчиков строк
IF m.proc_lvl=3
proc_now=m.proc_now+1 && текущий шаг %
=SHOW_PROC() && показ % выполнения
ENDIF
IF ADD_STR(m.tbl__dtl,4,m.tek_alias)#1 && для каждой строки по текущей группе
RETURN 0
ENDIF
ENDSCAN
RETURN 1
*############################################################################################
*############################################################################################
*############################################################################################
FUNCTION ADD_STR && добавление объектов по разделу
LPARAMETERS t_rnomer,t_rztype,t_alias
* t_rnomer - номер раздела
* t_rztype - тип раздела
* t_alias - surs с данными
*--------------------------------------------------------------------------------------------
LOCAL i,err_now,f_ret
PRIVATE tmp_name,tmp_func,ali_func,tmp_fusr,tmp_case,tmp_cusl,tmp_crun,tmp_fend,tmp_fout,znh_now,znh_val,znh_con,tmp_code
tmp_case=0 && ID CASE, объекты которого будут добавлены
SELECT _rtfreport
SCAN FOR rnomer=m.t_rnomer
DO CASE
CASE obkolv=1 && управляющие теги
f_ret = FWRITE(m.f_out,beetw_text) && пишем в вых. файл
IF m.f_ret<0
rep_errs='Ошибка записи в выходной файл!'
RETURN -1
ENDIF
CASE obtype=12 && ENDPAGE
IF !EMPTY(objusl) && есть условие применения
IF !EMPTY(m.t_alias)
SELECT (m.t_alias)
ENDIF
TRY
tmp_crun=IIF(EVALUATE(ALLTRIM(_rtfreport.objusl)),1,0)
CATCH
tmp_crun=0 && ошибка задания условия будет проигнорирована так, как будто условие не задавали вовсе
ENDTRY
SELECT _rtfreport
IF m.tmp_crun=1 && условие выполнено
f_ret = FWRITE(m.f_out,'\page \par '+beetw_text) && пишем в вых. файл
ELSE
f_ret = FWRITE(m.f_out,beetw_text) && пишем в вых. файл
ENDIF
ELSE
f_ret = FWRITE(m.f_out,IIF(RECNO(m.t_alias)<RECCOUNT(m.t_alias),'\page \par ','')+beetw_text) && пишем в вых. файл
ENDIF
IF m.f_ret<0
rep_errs='Ошибка записи в выходной файл!'
RETURN -1
ENDIF
CASE m.tmp_case=0 AND INLIST(obtype,13,14) && CASE,OTHERWISE, заходим вычислить ID CASE, который будет отрабатывать
tmp_crun=1 && 1-выводить этот CASE
IF obtype=13 && для CASE вычисляем выражение, OTHERWISE проскочит полюбому
tmp_cusl=ALLTRIM(SUBSTR(_rtfreport.f_name,AT("=",_rtfreport.f_name)+1)) && условие CASE
tmp_cusl=GET_FUNCONV(m.tmp_cusl)
IF !EMPTY(m.t_alias)
SELECT (m.t_alias)
ENDIF
TRY
tmp_crun=IIF(EVALUATE(m.tmp_cusl),1,0)
CATCH
tmp_crun=0
ENDTRY
SELECT _rtfreport
ENDIF
IF m.tmp_crun=1
tmp_case=_rtfreport.caseid && признак выполнения CASE
f_ret = FWRITE(m.f_out,beetw_text) && пишем в вых. файл
IF m.f_ret<0
rep_errs='Ошибка записи в выходной файл!'
RETURN -1
ENDIF
ENDIF
CASE obtype=15 && ENDCASE
tmp_case=0
f_ret = FWRITE(m.f_out,beetw_text) && пишем в вых. файл
IF m.f_ret<0
rep_errs='Ошибка записи в выходной файл!'
RETURN -1
ENDIF
CASE !EMPTY(_rtfreport.caseid) AND _rtfreport.caseid#m.tmp_case && объекты включены в CASE с невыполненным условием
LOOP
OTHERWISE
tmp_name=ALLTRIM(_rtfreport.f_name)
IF LEFT(m.tmp_name,1)=="&" AND SEEK(VAL(SUBSTR(m.tmp_name,2)),"_rtfvables","k1") && нашли эту подстановку
tmp_name=ALLTRIM(_rtfvables.f_name)
tmp_func=UPPER(ALLTRIM(IIF(!EMPTY(_rtfreport.func_txt),_rtfreport.func_txt,_rtfvables.func_txt)))
ali_func=UPPER(ALLTRIM(IIF(!EMPTY(_rtfreport.func_ali),_rtfreport.func_ali,_rtfvables.func_ali)))
tmp_fusr=UPPER(ALLTRIM(IIF(!EMPTY(_rtfreport.func_usr),_rtfreport.func_usr,_rtfvables.func_usr)))
tmp_fend=UPPER(ALLTRIM(IIF(!EMPTY(_rtfreport.func_end),_rtfreport.func_end,_rtfvables.func_end)))
tmp_fout=UPPER(ALLTRIM(IIF(!EMPTY(_rtfreport.func_out),_rtfreport.func_out,_rtfvables.func_out)))
tmp_code=IIF(!EMPTY(_rtfreport.code_txt),_rtfreport.code_txt,_rtfvables.code_txt)
ELSE
tmp_func=UPPER(ALLTRIM(_rtfreport.func_txt))
ali_func=UPPER(ALLTRIM(_rtfreport.func_ali))
tmp_fusr=UPPER(ALLTRIM(_rtfreport.func_usr))
tmp_fend=UPPER(ALLTRIM(_rtfreport.func_end))
tmp_fout=UPPER(ALLTRIM(_rtfreport.func_out))
tmp_code=_rtfreport.code_txt
ENDIF
IF VARTYPE(m.t_alias)="C" AND !EMPTY(m.t_alias)
SELECT (m.t_alias)
ali_func=IIF(!EMPTY(m.ali_func),m.ali_func,m.t_alias)
ENDIF
err_now=0
znh_now=''
IF !EMPTY(m.t_alias)
tmp_recn=IIF(EOF(m.t_alias),0,RECNO(m.t_alias)) && запоминается текущая запись SURC курсора
ENDIF
*--------------------------------------------------------------------------------------------
* Попытка получения значения
*--------------------------------------------------------------------------------------------
TRY
IF EMPTY(m.tmp_func)
IF !EMPTY(m.ali_func)
SELECT (m.ali_func)
ENDIF
IF EOF() && проверяем, чтобы не было EOF() при обработке переменной
GO BOTTOM
ENDIF
znh_now=EVALUATE(m.tmp_name)
ELSE
DO CASE
CASE m.tmp_func=="SUM" && требуется посчитать по текущей таблице
CALCULATE SUM(&tmp_name) TO znh_now IN (m.ali_func)
CASE m.tmp_func=="MAX" && требуется посчитать MAX по текущей таблице
CALCULATE MAX(&tmp_name) TO znh_now IN (m.ali_func)
CASE m.tmp_func=="MIN" && требуется посчитать MIN по текущей таблице
CALCULATE MIN(&tmp_name) TO znh_now IN (m.ali_func)
CASE m.tmp_func=="CNT" && требуется посчитать кол-во по текущей таблице
CALCULATE CNT(&tmp_name) TO znh_now IN (m.ali_func)
CASE m.tmp_func=="AVG" && требуется посчитать среднее по текущей таблице
CALCULATE AVG(&tmp_name) TO znh_now IN (m.ali_func)
OTHERWISE
err_now=1
ENDCASE
ENDIF
znh_val=m.znh_now && запоминается вычисленное значение для использования во внешних ф-х
IF !EMPTY(m.tmp_fusr)
DO CASE
CASE m.tmp_fusr=="DAT" AND INLIST(VARTYPE(m.znh_now),"D","T")
znh_now=REP_DATAPROP(m.znh_now)
CASE m.tmp_fusr=="TDT" AND VARTYPE(m.znh_now)="T"
znh_now=TTOD(m.znh_now)
CASE m.tmp_fusr=="PN1" AND INLIST(VARTYPE(m.znh_now),"D","T","C")
znh_now=REP_PERNAME(m.znh_now)
CASE m.tmp_fusr=="PN2" AND INLIST(VARTYPE(m.znh_now),"D","T")
znh_now=REP_PERNAME(m.znh_now,"P")
CASE m.tmp_fusr=="PN3" AND INLIST(VARTYPE(m.znh_now),"D","T")
znh_now=REP_PERNAME(m.znh_now,"Q")
CASE m.tmp_fusr=="PN4" AND INLIST(VARTYPE(m.znh_now),"D","T")
znh_now=REP_PERNAME(m.znh_now,"H")
CASE m.tmp_fusr=="KOL" AND VARTYPE(m.znh_now)="N"
znh_now=REP_NUM_PROP(m.znh_now,1)
CASE m.tmp_fusr=="RUB" AND VARTYPE(m.znh_now)="N"
znh_now=REP_NUM_PROP(m.znh_now)
CASE m.tmp_fusr=="INT" AND VARTYPE(m.znh_now)="N"
znh_now=INT(m.znh_now)
CASE m.tmp_fusr=="DEC" AND VARTYPE(m.znh_now)="N"
znh_now=MOD(m.znh_now,1)
CASE m.tmp_fusr=="RD0" AND VARTYPE(m.znh_now)="N"
znh_now=ROUND(m.znh_now,0)
CASE m.tmp_fusr=="RD1" AND VARTYPE(m.znh_now)="N"
znh_now=ROUND(m.znh_now,1)
CASE m.tmp_fusr=="RD2" AND VARTYPE(m.znh_now)="N"
znh_now=ROUND(m.znh_now,2)
CASE m.tmp_fusr=="RD3" AND VARTYPE(m.znh_now)="N"
znh_now=ROUND(m.znh_now,3)
CASE m.tmp_fusr=="IMG" AND VARTYPE(m.znh_now)="C"
IF FILE(m.znh_now) && если есть этот файл
DO CASE
CASE UPPER(JUSTEXT(m.znh_now))=="PNG"
znh_now="{\pict\pngblip "+STRCONV(FILETOSTR(m.znh_now),15)+" }"
CASE UPPER(JUSTEXT(m.znh_now))=="JPG"
znh_now="{\pict\jpegblip "+STRCONV(FILETOSTR(m.znh_now),15)+" }"
ENDCASE
ENDIF
CASE m.tmp_fusr=="DIA" AND VARTYPE(m.znh_now)="C"
IF LEFT(m.znh_now,6)=="ERROR:"
tmp_fusr='' && обнуляем признак картинки, чтобы показать текст ошибки
ELSE
znh_now="{\pict\pngblip "+STRCONV(m.znh_now,15)+" }"
ENDIF
CASE m.tmp_fusr=="PAR" AND VARTYPE(m.znh_now)="C" && Актуально только для RTF
znh_now=STRTRAN(m.znh_now,CHR(13),"{\par }")
ENDCASE
ENDIF
znh_con=m.znh_now && запоминается вычисленное и преобразованное значение для использования во внешних ф-х
CATCH TO goto_error
err_now=1
ENDTRY
IF !EMPTY(m.t_alias) AND !EMPTY(m.tmp_recn)
GO m.tmp_recn IN (m.t_alias)
ENDIF
*--------------------------------------------------------------------------------------------
IF m.err_now=1
znh_now=ALLTRIM(_rtfreport.f_name)
ELSE
DO CASE
CASE VARTYPE(m.znh_now)="C"
DO CASE
CASE m.tmp_fend=="HEX"
znh_now=ENCODE_SYMBOLS(m.znh_now)
CASE m.tmp_fusr=="IMG" OR m.tmp_fusr=="DIA"
DO CASE
CASE m.tmp_fend=="RM1"
znh_now="{\pict\brdrs"+SUBSTR(m.znh_now,7)
CASE m.tmp_fend=="RM2"
znh_now="{\pict\brdrsh"+SUBSTR(m.znh_now,7)
CASE m.tmp_fend=="RM3"
znh_now="{\pict\brdrdb"+SUBSTR(m.znh_now,7)
CASE m.tmp_fend=="ML5" && масштабирование (уменьшение) картинки на 50%
znh_now="{\pict\picscalex50\picscaley50"+SUBSTR(m.znh_now,7)
ENDCASE
OTHERWISE
m.znh_now=ALLTRIM(m.znh_now)
ENDCASE
CASE VARTYPE(m.znh_now)="N"
DO CASE
CASE (m.tmp_fend=="BLK" OR m.tmp_fend=="BLZ") AND m.znh_now=0 && одна из ф-й BLANK ZERO
znh_now=''
CASE m.tmp_fend=="RAZ" OR m.tmp_fend=="BLZ"
znh_now=NUM_RAZDEL(m.znh_now)
CASE m.tmp_fend=="NUM"
znh_now=ALLTRIM(CHRTRAN(PADL(m.znh_now,30),".",","))
OTHERWISE
m.znh_now=PADL(m.znh_now,30)
ENDCASE
CASE VARTYPE(m.znh_now)="D"
m.znh_now=DTOC(m.znh_now)
CASE VARTYPE(m.znh_now)="T"
m.znh_now=TTOC(m.znh_now)
CASE VARTYPE(m.znh_now)="L"
DO CASE
CASE m.tmp_fend=="LRU"
m.znh_now=IIF(m.znh_now,"ДА","НЕТ")
OTHERWISE
m.znh_now=IIF(m.znh_now,"TRUE","FALSE")
ENDCASE
ENDCASE
*--------------------------------------------------------------------------------------------
* Пользовательская внешняя функция
*--------------------------------------------------------------------------------------------
IF !EMPTY(m.tmp_fout)
tmp_fout=IIF("ZNH_NOW"$m.tmp_fout OR "ZNH_VAL"$m.tmp_fout OR "ZNH_CON"$m.tmp_fout,m.tmp_fout,m.tmp_fout+"(m.znh_val)") && добавляем параметр со значением переменной
TRY
znh_now=EVALUATE(m.tmp_fout)
znh_now=IIF(VARTYPE(m.znh_now)#"C","",m.znh_now) && проверка, чтобы там снаружи не накосячили с типом возврата
CATCH
znh_now=m.tmp_fout && в случае ошибки показываем виновника торжества в отчете
ENDTRY
ENDIF
*--------------------------------------------------------------------------------------------
* Кодировка
*--------------------------------------------------------------------------------------------
DO CASE
CASE !EMPTY(m.tmp_code) && указана перекодировка поля
znh_now=STRCONV(ALLTRIM(m.znh_now),m.tmp_code)
CASE !EMPTY(m.reps_cod) && тотальная перекодировка файла
znh_now=STRCONV(ALLTRIM(m.znh_now),m.reps_cod)
ENDCASE
*--------------------------------------------------------------------------------------------
ENDIF
SELECT _rtfreport
f_ret = FWRITE(m.f_out,ALLTRIM(m.znh_now)+beetw_text) && пишем в вых. файл
IF m.f_ret<0
rep_errs='Ошибка записи в выходной файл!'
RETURN -1
ENDIF
ENDCASE
ENDSCAN