Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
2 / 2 / 0
Регистрация: 05.04.2017
Сообщений: 18
1

Формирование документов

14.04.2017, 13:27. Показов 1092. Ответов 9
Метки нет (Все метки)

Здравствуйте!
Такой вопрос.

Имеется шаблон, представляющий html код. В тексте html я придумал свои вставки вида %value_name:value_format%.
Например:
HTML5
1
2
3
<div class = "center">
    <h3>Акт №%act_no%<br>СДАЧИ-ПРИЕМКИ РАБОТ<br>от %act_date:date%</h3>
</div>
Думаю над классом, который принимает:
- шаблон документа в виде html кода
- массив значений переменных-вставок (предполагаю формировать xml строку, и/или перегрузку с параметром-объектом DataRow)
текст разбивается на куски:
string[0] = "<div class = "center"><h3>Акт №";
string[1] = "%act_no%";
string[2] = "<br>СДАЧИ-ПРИЕМКИ РАБОТ<br>от ";
string[3] = "%act_date:date%";
string[4] = "</h3>";
... и т. д.
Строим объект-таблицу, содержащую:
Имя переменной, тип переменной, индекс элемента массива строк-кусков.

Ну и затем подставляем значения (на примере получается индексы 1 и 3), и собираем с помощью StringBuilder готовый документ.

Выскажите, пожалуйста мнение по поводу такого подхода решения данной задачи формирования документа. Если не трудно покритикуйте.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.04.2017, 13:27
Ответы с готовыми решениями:

Формирование документов
Задание в том, чтобы БД Access формировала 3 документа. Структура документа создается в отчете....

База клиентов и формирование документов
Доброго времени суток, товарищи. Никогда не работал с Access, но появилась важная задача. Есть...

формирование документов с чертежной рамкой в java
Всем привет, прошу помощи!!! У меня на проекте нужно формировать документы с чертежной рамкой...

Формирование движений без перепроведения документов
Добрый день! Конфигурация Управление торговлей, редакция 11.1.6.17. Создал регистр накопления,...

9
Эксперт .NET
7535 / 5026 / 1197
Регистрация: 25.05.2015
Сообщений: 15,314
Записей в блоге: 14
14.04.2017, 14:16 2
А документ-то для десктопных программ типа Word, или всё-таки для интернета (сайтов и браузеров)?
0
2 / 2 / 0
Регистрация: 05.04.2017
Сообщений: 18
14.04.2017, 15:05  [ТС] 3
Браузер используется для на печати документа.
Информационная база, из которой берутся данные договоров, актов выполненных работ, строится документ в виде html странички, открывается в браузере и выдается на печать.
0
Эксперт .NETАвтор FAQ
9853 / 4808 / 1730
Регистрация: 11.01.2015
Сообщений: 5,988
Записей в блоге: 34
14.04.2017, 19:02 4
Цитата Сообщение от Roman1979NK Посмотреть сообщение
Если не трудно покритикуйте
Да без проблем
Цитата Сообщение от Roman1979NK Посмотреть сообщение
текст разбивается на куски:
C#
1
2
3
4
5
string[0] = "<div class = "center"><h3>Акт №";
string[1] = "%act_no%";
string[2] = "<br>СДАЧИ-ПРИЕМКИ РАБОТ<br>от ";
string[3] = "%act_date:date%";
string[4] = "</h3>";
WTF? Зачем вы делите файл на куски?
Шаблон храните просто как string. А подстановки - храните как Dictionary<string, string>. А подстановки - делайте просто через string.Replace, перебирая в цикле переменные из словаря.
0
2 / 2 / 0
Регистрация: 05.04.2017
Сообщений: 18
14.04.2017, 19:31  [ТС] 5
Спасибо, Шторм!
То есть получается первым проходом извлекаю все переменные (т.к. в моем случае, например, %act_date:date% означает что нужно преобразовать значение DataTime в строку). А Dictionary будет с типами <string, ValueInfo>, где в качестве ключа идет %act_date:date% т.е. заменяемая подстрока, а ValueInfo содержит значение, тип, форматирование.
1) И вторым проходом, используя массив текущих переменных выполняем замену?
2) А как быстрее, string.Replace или Regex.Replace?
0
Эксперт .NET
7535 / 5026 / 1197
Регистрация: 25.05.2015
Сообщений: 15,314
Записей в блоге: 14
14.04.2017, 19:37 6
2. Быстрее наверное StringBuilder.

Посмотрите ещё проект dotliquid.
0
Эксперт .NETАвтор FAQ
9853 / 4808 / 1730
Регистрация: 11.01.2015
Сообщений: 5,988
Записей в блоге: 34
14.04.2017, 20:40 7
Цитата Сообщение от Roman1979NK Посмотреть сообщение
То есть получается первым проходом извлекаю все переменные (т.к. в моем случае, например, %act_date:date% означает что нужно преобразовать значение DataTime в строку). А Dictionary будет с типами <string, ValueInfo>, где в качестве ключа идет %act_date:date% т.е. заменяемая подстрока, а ValueInfo содержит значение, тип, форматирование.
1) И вторым проходом, используя массив текущих переменных выполняем замену?
Да, типа такого.
Цитата Сообщение от Roman1979NK Посмотреть сообщение
2) А как быстрее, string.Replace или Regex.Replace?
На самом деле это не важно. В данном случае быстродействие не критично, вы не будете генерировать отчеты миллионами.
1
2 / 2 / 0
Регистрация: 05.04.2017
Сообщений: 18
15.04.2017, 12:19  [ТС] 8
А не подскажете, как опытные программисты передают если много параметров?
0
Эксперт .NETАвтор FAQ
9853 / 4808 / 1730
Регистрация: 11.01.2015
Сообщений: 5,988
Записей в блоге: 34
15.04.2017, 13:16 9
Цитата Сообщение от Roman1979NK Посмотреть сообщение
как опытные программисты передают если много параметров?
Если много параметров, опытные программисты делают класс. Его и передают.
1
2 / 2 / 0
Регистрация: 05.04.2017
Сообщений: 18
16.04.2017, 14:30  [ТС] 10
Вот что получилось:
Кликните здесь для просмотра всего текста
C#
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
    public class ParameterizedDocument
    {
        List<Tag> Tags;
 
        string html_doc_source;
 
        public ParameterizedDocument(string html_template)
        {
            html_doc_source = html_template;
 
            Tags = new List<Tag>();
 
            /*
             * %\w+(\:(\w+)?(\<[\w\s,]*\>)?)?%
             * \w+ -имя тега
             * (\:(\w+)?(\<[\w\s,]*\>)?)? -дополнительная информация по форматированию значения тега, не обязательное наличие
             * 
             * Формат записи тега
             * %ИмяТега[:ФорматЗначения[<СтрокаФорматирования>]]%
             * 
             */
 
            var values = Regex.Matches(html_doc_source, @"%\w+(\:(\w+)?(\<[\w\s,\.]*\>)?)?%");
 
            foreach (var item in values)
            {
                Tag tag = new Tag(__GetValueName(item.ToString()),
                                    __GetValueType(item.ToString()),
                                    __GetFormattingString(item.ToString()),
                                    item.ToString());
                Tags.Add(tag);
            }
        }
 
        public string BuildDoc(Dictionary<string, string> values)
        {
            string result = html_doc_source;
 
            __ClearTags();
 
            // Заполнили значения тегов
            foreach (var item in values)
            {
                var find_tag = Tags.Find(x => x.Name == item.Key);
                if (find_tag != null) find_tag.Value = item.Value;
            }
 
            // Выполняем замену
            foreach (var item in Tags) // Замена однотипна - вывести в отдельный метод
            {
                string val = __MakeTagValue(item);
                if (val == null) result = result.Replace(item.ReplaceableString, "");
                else result = result.Replace(item.ReplaceableString, val);
            }
 
            return result;
        }
 
        public string BuildDoc(DataRow row)
        {
            Dictionary<string, string> tag_values = new Dictionary<string, string>();
 
            foreach (DataColumn column in row.Table.Columns)
            {
                tag_values[column.ColumnName] = row[column.ColumnName].ToString();
            }
 
            string result = BuildDoc(tag_values);
 
            return result;
        }
 
        public string BuildDoc(string xml_string)
        {
            throw new NotImplementedException();
        }
 
        // Строим значение-строку, которую непосредственно вставляем в документ
        string __MakeTagValue(Tag in_tag)
        {
            if (in_tag.Value == null) return "";
 
            string result = "";
 
            string tag_value = "";
 
            // 1. Формирование формата вида значения
            if (in_tag.ValueType == "date")
            {
                tag_value = DateTime.Parse(in_tag.Value.ToString()).ToShortDateString();
            }
            else // По умлочанию или если явно указано string то просто без изменений
            {
                tag_value = in_tag.Value.ToString();
            }
 
            // 2. Теперь значение тега определено и имеет строковый вид. Проверка на валидность
            if (tag_value == null || tag_value == "") return "";
 
            // 3. Формирование строки как заказано клиентом в скобках <formatter_string>
            if (in_tag.FormatString != null)
            {
                result = in_tag.FormatString.Replace(in_tag.Name, tag_value);
            }
            else result = tag_value;
 
            return result;
        }
 
        void __ClearTags()
        {
            foreach (var item in Tags)
            {
                item.Value = null;
            }
        }
 
        // Извлекаем из строки скрипта тега: Имя тега
        string __GetValueName(string script)
        {
            var val_name = Regex.Match(script, @"%\w+(\:)?");
            if (val_name.Success) return val_name.Value.Trim('%', ':'); else return null;
        }
 
        // Извлекаем из строки скрипта тега: Тип значения тега
        string __GetValueType(string script)
        {
            var val_type = Regex.Match(script, @"\:\w+(\<)?");
            if (val_type.Success) return val_type.Value.Trim(':', '<', '%'); else return "string";
        }
 
        // Извлекаем из строки скрипта тега: Строку форматирования
        string __GetFormattingString(string script)
        {
            var format_str = Regex.Match(script, @"\<[\w\s\,\.]*\>");
            if (format_str.Success) return format_str.Value.Trim('<', '>'); else return null;
        }
    }
 
    class Tag
    {
        public Tag(string name, string valuetype, string formatstring, string replaceablestring)
        {
            Name = name;
            ValueType = valuetype;
            FormatString = formatstring;
            ReplaceableString = replaceablestring;
        }
 
        public string Name { get; private set; }
        public object Value { get; set; }
 
        // формирующая строка
        public string ValueType { get; private set; }
        public string FormatString { get; private set; }
 
        // Строка-вставка оригинал в тексте документа. Если два тега с одинаковыми именами но разными форматстроками, для нас это разные теги
        public string ReplaceableString { get; private set; }
    }


Теперь надо реализовать вставку таблицы.
Предполагаю написать отдельный класс, принимающий шаблон вида таблицы, формирует html-код и вставляет вместо специального тега в основном документе.

Добавлено через 2 часа 11 минут
Проверочный код:

Кликните здесь для просмотра всего текста
C#
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Data;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using SysClasses.HtmlDocuments;
 
namespace TestParamDoc
{
    class Program
    {
        static void Main(string[] args)
        {
            // Создать объект, который построит таблицу тегов value1 value2 а в строке поменяет %0% %1%
            //      и создает таблицу, даже наверное Dictionary<int,string>
            string doc_template =
@"Акт №%act_no%
СДАЧИ-ПРИЕМКИ РАБОТ
от %act_date:date%
Мы, нижеподписавшиеся, «Исполнитель», в лице индивидуального предпринимателя %fio% с одной стороны,
и «Заказчик», в лице индивидуального предпринимателя Иванова Ивана Ивановича,
с другой стороны, составили настоящий акт о том,
что Исполнителем в период %act_date_begin:date% – %act_date_end:date%
выполнены следующие работы по договору №%contract_no% от %contract_date:date%:
%act_data%
Указанная работа выполнена надлежащим образом, в установленный срок и в
соответствии с иными требованиями и заданиями Заказчика.
Общая стоимость выполненных работ составила %act_sum% (%act_sum_in_words%) рублей
без НДС, в связи с применением упрощенной системы налогообложения.
Заказчик адрес: ул. %addr_street%, дом. %addr_home%%addr_kv:<, кв. addr_kv>%
Исполнитель
Алешин Р. В. / ________________
%fio_short% / ________________";
 
 
            ParameterizedDocument param_doc = new ParameterizedDocument(doc_template);
 
            Dictionary<string, string> d = new Dictionary<string, string>();
            d["act_no"] = 30.ToString();
            d["act_date"] = "13-10-2017";
            d["fio"] = "Петров Петр Петрович";
            d["act_date_begin"] = "10-10-2017";
            d["act_date_end"] = "13-10-2017";
            d["contract_no"] = 40.ToString();
            d["contract_date"] = "01-10-2017";
            d["act_data"] = "***Table***";
            d["act_sum"] = "12";
            d["act_sum_in_words"] = "Двенадцать";
            d["addr_street"] = "Косыгина";
            d["addr_home"] = "39";
            d["addr_kv"] = "78";
            d["fio_short"] = "Петров П.П.";
            string html_doc = param_doc.BuildDoc(d);
            Console.WriteLine(html_doc);
 
            Console.WriteLine(new string('=', 20));
 
            DataTable t = new DataTable();
            t.Columns.Add("act_no", typeof(int));
            t.Columns.Add("act_date", typeof(DateTime));
            t.Columns.Add("fio", typeof(string));
            t.Columns.Add("act_date_begin", typeof(DateTime));
            t.Columns.Add("act_date_end", typeof(DateTime));
            t.Columns.Add("contract_no", typeof(int));
            t.Columns.Add("contract_date", typeof(DateTime));
            t.Columns.Add("act_data", typeof(string));
            t.Columns.Add("act_sum", typeof(int));
            t.Columns.Add("act_sum_in_words", typeof(string));
            t.Columns.Add("addr_street", typeof(string));
            t.Columns.Add("addr_home", typeof(string));
            t.Columns.Add("addr_kv", typeof(string));
            t.Columns.Add("fio_short", typeof(string));
            DataRow row =
                t.Rows.Add(
                            150,
                            DateTime.Parse("13-10-2017"),
                            "Фролов Артем Борисович",
                            DateTime.Parse("10-10-2017"),
                            DateTime.Parse("13-10-2017"),
                            4,
                            DateTime.Parse("01-10-2017"),
                            "***Table***",
                            120,
                            "сто двадцать",
                            "Березина",
                            "23",
                            null,
                            "Фролов А.Б."
                        );
            string html_doc2 = param_doc.BuildDoc(row);
            Console.WriteLine(html_doc2);
 
            Console.ReadLine();
        }
    }
}
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.04.2017, 14:30

Заказываю контрольные, курсовые, дипломные работы и диссертации здесь.

Формирование документов с авторазмещением графических элементов
Необходимо разработать программу для формирования документов в формате PDF. На документ должны...

Как ускорить формирование документов (Excel) в Delphi
Имеется программа (САПРТ ТП), написанная на Delphi 7. В программе имеется возможно генерировать...

Автоматическое формирование содержания для нескольких Word документов
при создании макроса у меня появляется Application.Templates( _ ...

Макросы OpenOffice/формирование документов, какую прогу надо делать?
Помогите, плиз! Макросы OpenOffice/формирование документов, какую прогу надо делать?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.