Как стать автором
Обновить

Комментарии 43

Странный вопрос — если слова нумеруются с 1, то зачем вы цикл крутите с 0?

for (int i=0; i<sdoc.Words.Count;i++)

прекрасно заменится на
for (int i=1; i<=sdoc.Words.Count;i++)


И вам не надо будет использовать i+1 в следующих выражениях
if (sdoc.Words[i+1].Text.Trim()==keyWord)

keyWordEntries.Add(new keyWordEntry(keyWord,i+1,sdoc.Words[i+1].Text.Remove(0,keyWord.Length)));


А foreach там не работает?
там идет обращение к рядам DataTable, а они нумеруются с нуля как приличные :) пришлось бы у них писать i-1
foreach работает, но через for индекс слова получить быстрее
хотя к поиску слов это не относится, просто привычка
а вот когда по параграфам бежишь — актуально
а че будет, если использовать формат Office Open XML?

Наверняка всё упростится и ускорится.
на счёт упростится — не уверен, я препарировал docx — не всё там так просто
с точки зрения времени исполнения программы, наверно будет быстрее, но конкретно в моей задаче это не принципиально
второе, оператору придется заниматься конвертацией в docx (большая часть шаблонов будет все равно приходить в традиционном doc) — у него и так дел хватает
OpenXML SDK 2.0 не поможет?
Там Word вообще не нужен.
т.е. предлагаете: взять документ doc, без ворда конвертнуть его в опен-документ-фориат, произвести необходимые манипуляции, записать обратно в doc без ворда
почему-то я почти уверен, что разметка вся полетит к чертовой матери, особенно если создатель шаблона не пользовался стилями
да и трудоемкость задачи увеличивается в разы
ну если судить по эмоциональным рассказам моего коллеги об этом SDK, типа вот этого
winfs.ru/blogs/gollum/archive/2009/07/10/openxml-sdk-2-0-create-worksheet.aspx

То — не поможет. Вернее поможет но лучше не надо — столько геммороя.
Для шаблонов, где нужно только подставлять строки/числа в нужные места лучше воспользоваться таким типом полей как DocVariable и использовать их.

А вообще не лучше ли воспользоваться odftoolkit.org/ и генерить напрямую ODF? Сам не использовал, но может это менее ужасная вещь, чем вордовый API?
отвечу в третий раз, больше не буду :)
рассказать что такое ДокВариабл, лицу с юридическим образованием — весьма затруднительно
генерировать документ хоть с каким-то оформлением напрямую из кода — задача для мазохиста тем более, что мне не улыбается писать код под каждое письмо
да, еще добавлю, что основным форматом обмена идёт doc, и изменить это не в моих силах
Зачем рассказывать? Или я неправильно понял, что составляется шаблон письма, в котором задаются места, куда надо вписать нужные данные и потом на основе этого шаблона генерится некое количество писем. В этом случае при любых раскладах придётся самому залезть в шаблон и поменять ФИО например на нужную вставку. А если же это вставляет лицо с «юридическим образованием», то объяснить, что «вместо ФИО надо сделать следующее: зайти на вкладку *** нажать кнопку „вставить поле“ выбрать пункт *** и ввести ***». Люди с экономическим образованием врубались раза со второго в худшем случае, а проблем программисту убавлялось ощутимо.

Что проще, написать код вида:
[code]
WordDocument.Variables[«replace1»].Value = «This is a test»;
WordDocument.Variables[«replace2»].Value = «it's only a test!»;
WordDocument.Fields.Update;
[/code]

и совсем немного напрячь составителя шаблонов или использовать ваш изврат?
ваш подход более верный, но не в моём случае
к составителям шаблонов прямого доступа нет и меняются они регулярно, плюс поддержка переменных документа появилась, если я всё правильно помню только в 2003 (опять же я не могу контролировать создателей документов)
ну и на последок, так просто обратится к ним получится из VBA, а через API сходное количество возни :)

В том-то и дело, что всей возни в итоге сильно меньше. А VBA код на C# отображается практически 1:1.

«все несчастливые семьи несчастливы по своему» (С)
позанудничаю :)
1. всё равно придется строить список переменных задействованных в документе
2. в апи, variables — это не массив, а коллекция, т.е. работаем с ними подобным кодом
foreach (Variable var in WordDocument.Variables)
{
   switch (var.Name)
   {
          case "A": someLogik; break;
          case "B": someLogik; break;
   };
};

Тем не менее, соглашусь с тем, что код получается более понятный и багоустойчивый, в качестве эксперимента введу в оборот
в том-то и фишка, что можно обратиться к элементу коллекции, а не прочёсывать всю. Read MSDN, там это точно было.
можно, по индексу, но не по имени
или преобразовать в другой тип коллекции

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

Вместо DocVariables можно использовать bookmarks, но это несколько менее удобно.
Если есть желание, могу найти в завалах своих исходников примеры работы с этим делом.
это на самом деле не важно, как обращаться к переменным
в этой задаче интересно другое, что сократилось время формирования многостраничного документа на два порядка
в том-то и дело, что при использовании переменных документа такая проблема даже не возникает. Microsoft за тебя уже подумал, %username%
поясните? как это не возникает?
есть исходный документ 3-и страницы, нужно сформировать из него документ для 100 абонентов (300 страниц) — как в этом деле нам помогут переменные?
алгоритм:
1. открываем документ
2. устанавливаем переменные документа
3. делаем WordDocument.Fields.Update()
4. выводим на печать
5. завершаем ворд.

в том-то и прикол, что самомтоятельно шерстить документ не надо.

Единственный прокол, если используются Shapes, то надо по каждой Shape пройтись отдельно и вызвать Fields.Update(). Это не очень тривиальная штука, но ничего сверхсложного.
не выйдет, условия задачи не соблюдены — нужно не тупо вывести на печать, а сформировать документ (со всеми абонентами), который может быть подвергнут постобработке
вместо «выводим на печать» читаем «сохраняем на диск», суть не изменится.

не притворяйтесь глупее, чем вы есть :)
и как передавать: сто файлов вместо одного? я не изверг :)
можно конечно по папочкам разложить… но не удобно
ну и ниже отписал: печатной машине проще заглотить один документ на сотню страниц, чем сотню документов по одной странице
и еще проблема (ну опять же апликейшн-специфик), на печать выводиться может в другом месте, на непредсказуемых аппаратах (к ним, кстати, всё поступает уже в pdf, но это уже другая история)
а это называется «жопа» :) печатать на разных принтерах, на бланках строгой отчётности. но тут уже приходится самому с шаблонами работать.
слава богу, у нас без «строгой отчетности»
А бывает и так. Вот тогда становится весело. при этом бланк еще и «не совсем» A4 :)
стоп, что-то я не понял, поясните чуть подробнее задачу? нужен один документ с N письмами сформироваными из шаблона?
ага, именно
тогда несколько хитрее:
1. создаем пустой документ
2. копируем стили из шаблона
3. создаём документ из шаблона
4. копируем созданый документ в созданный на шаге 1
5. переходим к шагу 3.
6. сохраняем документ.

Я по такой схеме вполне успешно генерил доки из шаблонов на несколько страниц, в паре десятков экземпляров из 1С :) время работы вполне приемлимое.
основной прикол в том, что если начать вставлять документ с конца, то время выполнения операции значительно сокращается
сейчас я подумал о том, что можно и в самое начало вставлять, но тогда больше головняка с пейджбрейками будет
не так много как кажется. после каждого копипаста добавляется PB и вставляется следующая копипаста.
стал смотреть «как было»
оператор копировал макрос в полученный документ
потом вместо «иван иваныч» ставил доквариаблу
документ формировался как раз вставляя новую порцию в конец документа (работало крайне медленно, на 100 абонентов документ формировался минут 40)
в общем, мало того, что всё тормозило, так еще и операторы ошибались постоянно, и переделывали раз по несколько один и тот же документ

собственно, задача у меня была избавиться от манипуляций с вордовым макросами, повышение скорости — это чисто бонус клиенту
поправил пост :)
для меня это было очевидно, но видимо не донёс :)
ворд-эксель на каждом углу вагонами примеры, правда из них еще надо найти работающий с последней версией… :)
а вот CorelDRAW, Illustrator, PageMaker вот это было прикольно, правда PageMaker верстальщики не осилили пришлось перенаправить в ворд, который потом теже верстальщики по инструкции импортировали в PageMaker.
совсем не то
очень отдаленно напоминает :)
Есть стандартная функция Replace для замены текста. Она прекрасно справляется со своими обязанностями по замене и вставке нужных данных в шаблоне. И никаких самопальных алгоритмов по распознаванию и поиску слов.

Selection.Find.Execute(Replace := wdReplaceAll);
Спасибо. Логично.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории