Форум » [x]Harbour » Как использовать DOC-файл в качестве шаблона ? » Ответить

Как использовать DOC-файл в качестве шаблона ?

Andrey: Всем привет. Подскажите как можно реализовать печать Word-документа, в котором в нужном месте нужно поставить значение из полей БД или просто вычисляемые переменные (штук 20). Т.е. есть заготовка SAMPLE.DOC, в ней нужно поставить в нужных местах @POLE_NUM и т.д., а в программе на хХарборе, открыть этот документ (это я знаю как) и проставить по всем @xxxxx соответствующие значения (это я не знаю как). Может это нужно делать по другому, тогда подскажите как. Заранее спасибо.

Ответов - 33, стр: 1 2 All

Pasha: В документе создать в нужном месте закладки oWord := TOleAuto():New( "Word.Application" ) oDocs := oWord:Documents oDocs:Open( cFile ) oActive := oWord:ActiveDocument oSelect := oWord:Selection oMarks := oActive:BookMarks aBM := {} AADD(aBM, 'Дата', '"'+RTrim(Str(Day(Date)))+'" '+Month(Date)+Str(Year(Date),5)+' р.') AADD(aBM, 'Сумма', StrTran(Str(Summa, 12, 2), '.', ',')) ... SetWMarks(oWord, oMarks, aBM) oActive:Saved := .t. oWord:Visible := .t. Function SetWMarks(oWord, oBookMarks, aMarks) Local oSelect := oWord:Selection Local oBookMark, cName, nBM, xValue for each oBookMark in oBookMarks cName := HB_AnsiToOEM(oBookMark:Get('Name')) xValue := nil if (nBM := ASCAN(aMarks, {|a| Upper(a[1]) = Upper(cName)})) # 0 xValue := aMarks[nBM][2] endif if xValue # nil oBookMark:Select() oSelect:Invoke("InsertAfter", HB_OemToAnsi(xToSt(xValue)) ) endif next Return nil

Andrey: Pasha пишет: В документе создать в нужном месте закладки А как их создать ? Чуть подробнее в этом месте.... А если можно и не жалко рабочий пример кинуть мне на мыло 30195@mail.ru ? Буду очень благодарен.

Pasha: Переместить курсор в нужную позицию документа Вставка - Закладка Набрать имя закладки (у меня это "Дата", "Сумма") Добавить ЗЫ Закладкой можно помечать и выделенную область документа Пример выслать сложновато... это ведь exe и БД Пробуй, там ничего сложного нет


Andrey: Спасибо, вроде все получилось. Только как после ВСТАВОК курсор в WORD'e вернуть на верх документа ? И второе, как отправить на печать 5 копий сразу ?

Pasha: Включаешь Сервис - Макросы - Начать Запись Нажимаешь Ctrl - PgUp, затем печать 5 копий сразу Останавливаешь запись, смотришь что получилось: Selection.HomeKey Unit:=wdStory Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _ wdPrintDocumentContent, Copies:=5, Pages:="", PageType:=wdPrintAllPages, _ ManualDuplexPrint:=False, Collate:=True, Background:=True, PrintToFile:= _ False, PrintZoomColumn:=0, PrintZoomRow:=0, PrintZoomPaperWidth:=0, _ PrintZoomPaperHeight:=0 Запускаешь справку по Word VBA, смотришь значение константы wdStory Затем смотришь метод PrintOut Переводишь ключевые параметры в позиционные Получаешь: oSelect:HomeKey(6) oWord:PrintOut(...)

Andrey: Спасибо !!!

Andrey: Пытаюсь открыть файл WORD'ом *.ТХТ в кодировке OEM или WINDOWS Получил макрос: ChangeFileOpenDirectory "C:\BIN\" Documents.Open FileName:="TXT2SLK.TXT", ConfirmConversions:=False, _ ReadOnly:=False, AddToRecentFiles:=False, PasswordDocument:="", _ PasswordTemplate:="", Revert:=False, WritePasswordDocument:="", _ WritePasswordTemplate:="", Format:=wdOpenFormatAuto, XMLTransform:="", _ Encoding:=866 Подскажите правильный перевод в хХарбор, подробнее, чтоб понятно было и я не буду приставать потом с такими пустяками ! Заранее спасибо.

Петр: Andrey пишет: Подскажите правильный перевод в хХарбор, подробнее, чтоб понятно было и я не буду приставать потом с такими пустяками ! Так подробнее или чтоб понятно было ? И если для тебя это такой пустяк, то зачем приставать ? Тебе не приходило в голову, что для "правильного перевода" нужно иметь не только обобщенное понятие об ООП, но и его реализации в VBA(VB6), [x]Harbour, особенностях реализации класса TOleAuto ? В любом случае ловлю на слове. Если ты получил макрос - то уже знаешь самое главное - как открыть редактор Visual Basic. На всякий случай напомню: находясь в Ворде нажимаешь ALT-F11 (или меню Сервис -> Макрос -> Редактор VB ) Далее в редакторе нажимаешь F2 (или меню View-> Object Browser ) Вот мы находимся в Object Browser - мощном средстве VB, с помощью которого можна получить море ценной информации. В выпадающем списке Project\Library (по умолчанию там установлено All Libraries) выбираем нужное, в нашем случае библиотеку Word. В поле ввода Search Word вводим искомое, для начала ChangeFileOpenDirectory и жмем кнопку Search ( такая с биноклем). Смотрим на Search Results Видим, что ChangeFileOpenDirectory есть членом (member) двух класов Application и Global библиотеки Word. Интуитивно понимаем, что нам лучше воспользоваться классом Application. Видим также, что ChangeFileOpenDirectory это метод (характерный зеленый значек). Ниже находим сл. Sub ChangeFileOpenDirectory(Path As String) Значит нарисовалась такая цепочка библиотека Word - класс Application - метод ChangeFileOpenDirectory с параметром Path У нас все готово для перевода в хХарбор Значит oWord := TOleAuto():New( "Word.Application" ) oWord:ChangeFileOpenDirectory( "C:\BIN\" ) Теперь дальше: ищем Open. Здесь у нас выбор побогаче Но, впрочем, интересоваться мы будем лишь классом Documents Function Open(FileName, [ConfirmConversions], [ReadOnly], [AddToRecentFiles], [PasswordDocument], [PasswordTemplate], [Revert], [WritePasswordDocument], [WritePasswordTemplate], [Format], [Encoding], [Visible], [OpenAndRepair], [DocumentDirection], [NoEncodingDialog], [XMLTransform]) As Document Значит так oWord:Documents:Open( ... ) впрочем, чаще пишут так oDocs := oWord:Documents oDocs:Open( ... ) равнозначно, но удобнее. Разберемся с параметрами метода Open с помощью справки Microsoft Visual Basic ( легче всего сделать так: щелкнуть мышью по нижней панели Object Browser, там где Function Open(FileName, .. и нажав F1, выбрать необходимое, в нашем случае Open method as it applies to the Documents object ). Обрати внимание на то, что некоторые параметры в справке определены как Optional Variant, некоторые Required. По сути тебе надо передать 3 параметра из 16 : FileName ( 1 в списке параметров), Format := wdOpenFormatAuto (10), Encoding:=866 (11). В VBA есть такая примочка - поименнованые параметры (или ключевые). Это дает возможность, например, написать так Documents.Open AddToRecentFiles:=False, FileName:="TXT2SLK.TXT" или так Documents.Open FileName:="TXT2SLK.TXT", AddToRecentFiles:=False не заботясь о порядке следования параметров. Еще VBA (С++) поддерживает значение параметра по умолчанию. В хХарбор такие вещи не проходят (если только с препроцессором не нашаманишь), ну да и не надо. По привычке можно написать Open( cFile,,,,,,,,,0,"866") - но это работать не будет, более того приведет к ошибке времени исполнения. Сработает Open( cFile, .f., .f., .f., "", "", .f., "", "", 0,"866") Т.е.если ты собрался передать несколько параметров из [x]Harbour, например, как в нашем случае 1, 10, 11, то тебе придется передавать параметры с 1 по 11. Так реализован класс TOleAuto. Если метод принимает 20 параметров, а реально ты используешь 1 и 20, готовся передавать все 20. Передавать следует или значения по умолчанию ( см.справку ) или требуемое значение, не NIL. Также в данном случае обрати внимание на 0 - это значение константы wdOpenFormatAuto, его тоже легче всего найти с помощью Object Browser. Значит окончательно cFile := "1.txt" oWord := TOleAuto():New( "Word.Application" ) oWord:ChangeFileOpenDirectory( "C:\BIN\" ) oDocs := oWord:Documents oDocs:Open( cFile, .f., .f., .f., "", "", .f., "", "", 0,"866") Voila.. P.S. В данном случае я использовал Office 2003. P.P.S. Пример для разбора ты выбрал сам. IMHO для обработки текстовых файлов возможностей [x]Harbour выше крыши. Мог бы переспросить о печати 5 копий или еще чего-тщ посложнее.

Andrey: Спасибо большое Петр !!! Петр пишет: Мог бы переспросить о печати 5 копий или еще чего-тщ посложнее. А можно переспросить про это ? Меня не пошлют, куда подальше ?

Петр: Andrey пишет: А можно переспросить про это ? Про что это ? 5 копий? Вот макрос Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _ wdPrintDocumentContent, Copies:=5, Pages:="", PageType:=wdPrintAllPages, _ ManualDuplexPrint:=False, Collate:=True, Background:=True, PrintToFile:= _ False, PrintZoomColumn:=0, PrintZoomRow:=0, PrintZoomPaperWidth:=0, _ PrintZoomPaperHeight:=0 Видим, что нужно использовать метод PrintOut класса Application, который, как уже мы знаем помещен в библиотеку Word значит oWord := TOleAuto():New( "Word.Application" ) .. oWord:PrintOut(...) Теперь разберемся с параметрами Из справки Sub PrintOut([Background], [Append], [Range], [OutputFileName], [From], [To], [Item], [Copies], [Pages], [PageType], [PrintToFile], [Collate], [FileName], [ActivePrinterMacGX], [ManualDuplexPrint], [PrintZoomColumn], [PrintZoomRow], [PrintZoomPaperWidth], [PrintZoomPaperHeight]) Находим с помощью Object Browser или справки значения констант, теперь одним глазом смотрим на макрос, вторым подглядываем в справку на значения параметров по умолчанию и подставляем параметры ( с 1 по 8 - 8 параметр и есть заветное число копий, в нашем случае 5, остальные нам по условию задачи не нужны ) и получаем #define wdPrintAllDocument 0 #define wdPrintDocumentContent 0 #define wdPrintAllPages 0 oWord := TOleAuto():New( "Word.Application" ) oDocs := oWord:Documents oDocs:Open(...) oWord:PrintOut( .t., .f., wdPrintAllDocument, "", "", "", wdPrintDocumentContent, 5 ) //, "", wdPrintAllPages, .f., .t., "", "", 0, 0, 0, 0 ) oWord:Quit() Можно обойтись без oDocs:Open(...) но тогда нужно задать значение параметру FileName, в нашем случае оно равно "", т.е. будет печататься активный документ, открытый с помощью метода Open. Andrey пишет: Меня не пошлют, куда подальше ? Возможно так бы и получилось.. Но в этом методе есть небольшой подвох. Прочитав справку From Optional Variant. The starting page number when Range is set to wdPrintFromTo. To Optional Variant. The ending page number when Range is set to wdPrintFromTo так и тянет написать oWord:PrintOut( .t., .f., wdPrintAllDocument, "", 0, 0.. и получить ошибку. К тому же попробуй догадайся, что ActivePrinterMacGX нужно определить как "" не читая Help included with Microsoft Office Macintosh Edition.

Andrey: Спасибо Петр. Пошел разбираться. Куда пиво отправить ?

Andrey: Залез в хелп, нашел что хотел и обломс.... SaveAs(FileName, FileFormat, LockComments, Password, AddToRecentFiles, WritePassword, ReadOnlyRecommended, EmbedTrueTypeFonts, SaveNativePictureFormat, SaveFormsData, SaveAsAOCELetter, Encoding, InsertLineBreaks, AllowSubstitutions, LineEnding, AddBiDiMarks) Пытаюсть полученный текст записать под другим именем как doc-файл, где cFileDoc := "C:\test_word\test.doc" oDocs:SaveAs( cFileDoc, wdFormatDocument,.f.,"",.t.,"",.f.,.f.,.f.,.f.,20880,.f.,.f.,0,.f.) Вываливается с ошибкой..... Error Word.Application:DOCUMENTS/16389 E_FAIL: SAVEAS Arguments: ( [ 1] = Type: C Val: E: \@MyWork\my_HARBOUR\Word_Txt\mar02.doc [ 2] = Type: N Val: 0 [ 3] = Type: L Val: .F. [ 4] = Type: C Val: [ 5] = Type: L Val: .T. [ 6] = Type: C Val: [ 7] = Type: L Val: .F. [ 8] = Type: L Val: .F. [ 9] = Type: L Val: .F. [10] = Type: L Val: .F. [11] = Type: N Val: 20880 [12] = Type: L Val: .F. [13] = Type: L Val: .F. [14] = Type: N Val: 0 [15] = Type: L Val: .F.) Error at ...: TOLEAUTO:SAVEAS(0) in Module: win32ole.prg Called from : WORD2OPEN(70) in Module: Word_OpenTxt.prg Где копать ???

Петр: Andrey пишет: Где копать ??? Где копал, там и копай, только глубже Что представляет собой конструкция oDocs:SaveAs(..) ? Это вызов метода SaveAs(..) класса Documents ( oDocs := oWord:Documents ) Извини, но SaveAs(..) член класса Document, читай внимательно. Ты пытаешся вызвать несуществующий метод SaveAs() класса Documents - отсюда и ошибка. Внимательно прочитав справку ты б написал или oMyDocument := oDocs:Open( ... ) oMyDocument:SaveAs( cFileDoc, wdFormatDocument ) или oWord:ActiveDocument:SaveAs( cFileDoc, wdFormatDocument ) Вот так дружок

Лукашевский: Подскажите, плиз, функцию (или это называется метод?) для получения в ворде ширины текущей строки в символах. Задача стоит такая: текст до одной ширины - оставляем как есть, текст до другой ширины (что-то уже не влезает в A4) - уменьшаем шрифт, а вот если сильно не влезает - переворачиваем в Landscape. Это-то всё не вопрос, а вот как получить искомую ширину? Наверняка ведь кто-нибудь сталкивался?

Dimka: так так так. я не понял как все это выглядит. мы имеем doc-шаблон, например такой: {{ head }} Бла бла бла {% for i :=1 to 10 massiv: Номер {{ i }} : massiv --------------- endfor %} потом открываем из программы шаблон и вызываем метод, например, Render с параметрами для head и massiv. получаем файл. сохраняем. так?))) если нет, то плохо)))))) почитал тему - ничего не понял. мы сначала открываем файл, потом ставим закладки, а только потом рендерим???? так чтоли?

Andrey: Давай ящик, вышлю рабочий пример !

Лукашевский: Что-то на мой июньский вопрос никто ответил, хотя тема, как вижу, живая... Повторю попроще: как программно понять, влезет ли текущий документ при печати в границы печатного листа (в смысле правого края)?

Лукашевский: Петр Собираюсь печатать Word'овский документ постранично, т.е. каждую страницу выводить отдельным PrintOut'ом. Вопросик: как узнать, сколько всего страниц нужно напечатать? А то буду печатать третью там, четвёртую, а их всего две...

Петр: Узнать сколько страниц в документе можно так ?oWord:ActiveDocument:ActiveWindow:Panes(1/*i*/):Pages():Count

Лукашевский: Петр пишет: ?oWord:ActiveDocument:ActiveWindow:Panes(1/*i*/):Pages():Count Петр, заранее спасибо, но сразу по тексту вопрос: i - это какая-то переменная?

Петр: i это индех обьекта Pane из коллекции Panes, как правило в несложных случаях используйте i := 1, не ошибетесь. Из справки : A window has more than one pane if the window is split or the view is not print layout view and information such as footnotes or comments are displayed.

Лукашевский: Ещё раз спасибо.

Andrey: Подскажите пожалуйста, как программно задать параметры страницы документа ?

Петр: #xtranslate CentimetersToPoints( <w> ) => (<w> * 28.35 ) oWord := CreateObject( "Word.Application" ) oWord:Documents:Add() WITH OBJECT oWord:ActiveDocument:PageSetup :TopMargin := CentimetersToPoints(2.1) :BottomMargin := CentimetersToPoints(2.1) :LeftMargin := CentimetersToPoints(2.3) :RightMargin := CentimetersToPoints(1.7) :Gutter := CentimetersToPoints(0) :HeaderDistance := CentimetersToPoints(1.25) :FooterDistance := CentimetersToPoints(1.25) :PageWidth := CentimetersToPoints(21) :PageHeight := CentimetersToPoints(29.7) // и т.д. END WITH

Лукашевский: Есть ли в xHarbour'е функция OleUninitialize() ? А то я раскопал Harbour'ный примерчик, а линковка на эту функцию выдаёт ошибку Unresolved external... Очень было бы полезно это и в xHarbour, а то если программа вываливается на ошибке в процессе работы объектом OLE, то объект так и остаётся висеть в системе, и пока его задачу не снимешь, ничего с файлом с тем же именем, что был открыт (например PRICELST.DBF) сделать невозможно! Ну не объяснять же юзверям - нажмите Alt Ctrl Del и так далее, - они же десять раз нажмут, запустят перезагрузку компа и меня же в этом обвинят!

Pasha: Функция OleUninitialize() в этом случае не поможет, так как для снятия приложения необходимо напрямую вызвать некоторый метод. К примеру, для MS Office - это oWord:Quit(), oExcel:Quit() Вызов такого метода можно прописать в exit-процедуре. К примеру: if ValType(oWord) == 'O' oWord:Quit() endif или ловить ошибку в begin sequence - end

Лукашевский: Pasha пишет: OleUninitialize() в этом случае не поможет А для чего она тогда вообще предназначена? Мне же не обязательно снимать приложение, достаточно закрыть OLE-объект, связанный с файлом. Но этот разговор ни о чём - функции-то нет... Pasha пишет: if ValType(oWord) == 'O' oWord:Quit() endif И ещё oWord надо объявлять как public... Но да, наверное придётся так.

Pasha: Лукашевский пишет: А для чего она тогда вообще предназначена? функция WINOLEAPI OleInitialize(IN LPVOID pvReserved); инициализирует библиотеку ole, а функция WINOLEAPI_(void) OleUninitialize(void); закрывает ее и освобождает все ресурсы Запущенные приложения надо закрывать их методами Вместо exit-процедуры можно ловить ошибку стандартными средствами clipper/harbour

Лукашевский: Pasha пишет: Запущенные приложения надо закрывать их методами Да не приложение мне надо закрыть, а по-минимуму - всего лишь объект! Вот я и думал, что может OleUninitialize() закрывает все созданные программой OLE-объекты... Кстати говоря, OLE вроде бы срабатывает шустрее, если Word или там Excel на момент обращения к OLE висит в памяти.

Pasha: Лукашевский пишет: Да не приложение мне надо закрыть, а по-минимуму - всего лишь объект! Обьект TOleAuto и запущенное приложение - это разные вещи Обьект само собой закрывается, т.е выполняется его деструктор end При этом приложение остается в памяти.

Лукашевский: Pasha пишет: Обьект TOleAuto и запущенное приложение - это разные вещи И я именно об этом, о том что объект можно закрыть без закрытия самого приложения... А ты всё о закрытии приложений толкуешь... А oWord:Quit() закрывает и объект, и приложение.

Andrey: Кто работает с Офисом - смотрите ссылку: http://www.script-coding.com/MSOffice.html использование COM-серверов MS Office в скриптах Конвертация форматов файлов (Save As...) с помощью Excel и Word И т.д. Разработка скриптов - http://www.script-coding.com/index.html

pureproft: Уж коли заявлена мультиплатформенность инструмента смотри в сторону abiword ... с документом можно работать фактически как с текстом обычным парсингом или как XML



полная версия страницы