Delphi робота з MS WORD

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

Delphi: робота з MS WORD

Припустимо, у нас вже відкрито файл. Питання відкриття та збереження документів вже були в інших статтях, так що докладно на цьому зупинятися не будемо. Просто по ходу справи буде приведено те, чого раніше не траплялося - вихід з документа без збереження змін. Як-то забув, вибачте:)

Текст

Спочатку про найпростіше - додаванні в документ Word потрібного рядка тексту. Помістимо на форму компоненти WordDocument, WordApplicationі WordParagraphFormat з палітри Servers. Нас цікавлять в першу чергу властивість Range компонента WordDocument і властивість Selection компонента WordApplication. Класики стверджують, що вони є посиланням на об'єкти Range і Selection. Range представляє з себе, простіше кажучи, шматок тексту, це може бути як весь текст документа, так і будь-яка його частина. Його межі задаються двома (або менше) параметрами типу OleVariant.

Наприклад:

var range1, range2, range3, a, b: OleVariant;

...

range1: = WordDocument1.Range;

a: = 5;

b: = 15;

range2: = WordDocument1.Range (a, b);

range3: = WordDocument1.Range (a);

Перший наш об'єкт включає в себе весь текст документа, у другого ми обмежили межі 5-м і 15-м символами, третій представляє з себе весь подальший текст документа, починаючи з 5-го символу. Об'єкт має кілька корисних методів, наприклад, з його допомогою можемо додати текст в документ:

range2.InsertAfter ('MS Word');

Це ми вставили текст після виділеного Range. Точно також можемо вставити текст і перед ним, для цього служить метод InsertBefore (). Текст, укладений в об'єкті Range, можемо отримати так:

WordDocument1.Range (a, b). Text;

Крім того, за допомогою Range можемо змінити шрифт в межах об'єкта. Приклад:

a: = 5;

b: = 15;

WordDocument1.Range (a, b). Font.Bold: = 1;

WordDocument1.Range (a, b). Font.Size: = 14;

WordDocument1.Range (a, b). Font.Color: = clRed;

Якщо хочемо скасувати виділення жирним шрифтом, присвоюємо 0. Аналогічно можна зробити шрифт курсивом, підкресленим - наберіть WordDocument1.Range.Font., І середовище сама підкаже, які можуть бути варіанти. Методи Select, Cut, Copy і Paste працюють як у звичайному тексті. За допомогою Paste можемо на місце вибраного Range вставити не лише рядки, але й малюнок, що знаходиться в буфері обміну.

WordDocument1.Range (a, b). Select;

WordDocument1.Range (a, b). Cut;

WordDocument1.Range (a, b). Copy;

WordDocument1.Range (a, b). Paste;

За допомогою Range можемо знайти в документі потрібний рядок. Нехай у тексті міститься слово "picture". Наприклад, нам на його місце треба буде вставити малюнок.

var a, b, vstart, vend: OleVariant;

j, ilengy: Integer;

...

ilengy: = Length (WordDocument1.Range.Text);

for j: = 0 to ilengy-8 do begin

a: = j;

b: = j +7;

if WordDocument1.Range (a, b). Text = 'picture' then begin

vstart: = j;

vend: = j +7;

end;

end;

WordDocument1.Range (vstart, vend). Select;

Така процедура знаходить і виділяє потрібний шматок тексту.

Тепер про Selection, що вдає із себе виділений фрагмент документа. Якщо виділення немає, це поточна позиція курсору в документі. З його допомогою можемо вставити що-небудь на місце виділеного фрагмента, зробити вирівнювання, змінити шрифт. Він також має методи InsertAfter () і InsertBefore ():

WordApplication1.Selection.InsertAfter ("text1");

WordApplication1.Selection.InsertBefore ("text2");

Форматування виділеного тексту відбувається аналогічно Range, наприклад:

WordApplication1.Selection.Font.Bold: = 1;

WordApplication1.Selection.Font.Size: = 16;

WordApplication1.Selection.Font.Color: = clGreen;

Для вирівнювання простіше скористатися компонентом WordParagraphFormat. Спочатку тільки потрібно "підключити" його до виділеного фрагмента тексту:

WordParagraphFormat1.ConnectTo (WordApplication1.Selection.ParagraphFormat);

WordParagraphFormat1.Alignment: = wdAlignParagraphCenter;

Значення його властивості Alignment може приймати значення wdAlignParagraphCenter, wdAlignParagraphLeft, wdAlignParagraphRight, сенс яких очевидний. Є й методи Cut, Copy і Paste, які в поясненнях навряд чи потребують:

WordApplication1.Selection.Cut;

WordApplication1.Selection.Copy;

WordApplication1.Selection.Paste;

Прибираємо виділення за допомогою методу Collapse. При цьому необхідно вказати, в який бік зміститься курсор, чи буде він до раніше виділеного фрагмента або після:

var vcol: OleVariant;

...

vcol: = wdCollapseStart;

WordApplication1.Selection.Collapse (vcol);

При цьому виділення пропаде, а курсор займе позицію перед фрагментом тексту. Якщо привласнити змінній значення wdCollapseEnd, то курсор переміститься тому. Можна просто поставити в дужках "пустушку":

WordApplication1.Selection.Collapse (EmptyParam);

Тоді згортання виділення проводиться за замовчуванням, до початку виділеного тексту.

Малюнки

Логічно було б припустити, що малюнки документа будуть представляти із себе колекцію, аналогічну таблиць, і ми, звернувшись до конкретної картинці, зможемо міняти її властивості - обтікання, розмір і т.д. Однак нічого подібного в WordDocument не виявляється. Тому можливості управління вбудованими в документ зображеннями сильно обмежені.

Найпростіший метод вставити в документ малюнок - по згаданих причин він же і єдиний - скопіювати його в Word з буфера обміну. Припустимо, малюнок у нас знаходиться в компоненті DBImage. Спочатку треба загнати його в буфер обміну:

Clipboard.Assign (DBImage1.Picture);

Тепер для його вставки слід скористатися методом Paste об'єктів Range або Selection: WordApplication1.Selection.Paste або WordDocument1.Range (a, b). Paste. Залишити для малюнка достатня кількість порожніх рядків і потрапити в потрібне місце - це вже наша турбота. Якщо він потрапить посеред тексту, вигляд буде досить гидкий - при такій вставці обтікання текстом малюнка відбувається якось дивно. Можна приготувати для звіту шаблон, де замінюємо малюнком яке-небудь ключове слово. Про те, як знайти в документі потрібний текст, див. вище.

А тепер про дещо інший спосіб вставки малюнка, який усуває проблеми з обтіканням і дає нам можливість переміщати його по документу, масштабувати і задавати відступи між малюнком і текстом. Спосіб, власне, той самий - копіюємо з буфера обміну, але не прямо в документ, а в "рамку" - текстову вставку. У ній може знаходитися не тільки текст, але і картинка, чим і скористаємося.
"Рамки" утворюють колекцію Frames, нумеруються цілим індексом, що пробігають значення від 1 до WordDocument1.Frames.Count. Додамо до документа рамку, змінимо її розмір і вставимо малюнок:

Clipboard.Assign (DBImage1.Picture);

vstart: = 1;

vend: = 2;

WordDocument1.Frames.Add (WordDocument1.Range (vstart, vend));

i: = 1;

WordDocument1.Frames.Item (i). Height: = DBImage1.Height;

WordDocument1.Frames.Item (i). Width: = DBImage1.Width;

WordDocument1.Frames.Item (i). Select;

WordApplication1.Selection.Paste;

Тут для простоти передбачається, що розмір DBImage дорівнює розміру самої картинки, а також що до цього рамок у нас в документі не було. Звернути увагу слід на декілька моментів. Розмір рамки треба задавати до того, як копіювати в неї малюнок. Інакше вона буде мати розмір за замовчуванням, під який замасштабіруется і наша картинка. При спробі змінити розмір рамки заднім числом розмір картинки вже не зміниться. Крім того, параметр Range при додаванні рамки часто ніякої ролі не грає. Рамка спочатку все одно з'явиться в лівому верхньому кутку документа, а зазначений шматок тексту при цьому не постраждає. Але це тільки в тому випадку, якщо він не виділено. Якщо в документі є виділення, рамка з'явиться замість виділеного фрагменту. Таким чином можемо її вставити в потрібне місце замість якогось ключового слова.
При бажанні можемо її посувати в документі і "вручну". Для цього служать властивості горизонтального і вертикального позиціонування, які задають її відступ від лівого верхнього "кута" документа:

i: = 1;

WordDocument1.Frames.Item (i). VerticalPosition: = 30;

WordDocument1.Frames.Item (i). HorizontalPosition: = 50;

Відступ між краями рамки і текстом задається наступним чином:

WordDocument1.Frames.Item (i). HorizontalDistanceFromText: = 10;

WordDocument1.Frames.Item (i). VerticalDistanceFromText: = 10;

А тепер про масштабування. Для цього достатньо довжину і ширину рамки помножити на одне і те ж число. Наприклад:

WordDocument1.Frames.Item (i). Height: = DBImage1.Height * 1.5;

WordDocument1.Frames.Item (i). Width: = DBImage1.Width * 1.5;

При цьому наша картинка в півтора рази пропорційно розтягнеться. Точно також можна і зменшити, але ділити, як і множити, слід на одне число. Розтягувати довжину і ширину по-різному у мене особисто не виходило. Задавати розмір знову-таки треба ще до вставки малюнка. Ну і, нарешті, видалення рамки:

WordDocument1.Frames.Item (i). Delete;

Списки

Списки в документі утворюють колекцію Lists, до окремого списку звертаємося WordDocument1.Lists.Item (i), де i ціле число від 1 до WordDocument1.Lists.Count ... на цьому все. Ні методів, що дозволяють не те що створити новий список, а навіть додати пункт до вже існуючого. Нічого страшного, справжні герої завжди йдуть в обхід:)) Зараз ми все ж проробимо і те, й інше. Все що нам знадобиться - властивість Range окремого списку, тобто його текст без поділу на пункти, а також можливість його виділити:

WordDocument1.Lists.Item (i). Range.Select;

Для цього в будь-якому випадку буде потрібно заготовка. Неважливо, вставлена ​​вона до загального шаблонний документ або зберігається в окремому файлі. Заготівлю робимо так: вибираємо в меню Формат / Список, і зберігаємо, якщо це окремий шаблон списку. У нас з'являється порожній список без тексту з одним маркером. Далі згадуємо, як ми робили списки вручну - писали текст, натискали "Enter", з'являвся новий елемент списку. Тепер те ж саме, тільки програмно. Припустимо, у нас вже відкрито документ із заготівлею, і ми хочемо внести в список пункти "Item 1" і "Item 2":

var i: Integer;

vcol: OleVariant;

...

i: = 1;

vcol: = wdCollapseEnd;

WordDocument1.Lists.Item (i). Range.Select;

WordApplication1.Selection.Collapse (vcol);

WordApplication1.Selection.InsertAfter ('Item 1');

WordDocument1.Lists.Item (i). Range.Select;

WordApplication1.Selection.Collapse (vcol);

WordApplication1.Selection.InsertAfter (# 13);

WordDocument1.Lists.Item (i). Range.Select;

WordApplication1.Selection.Collapse (vcol);

WordApplication1.Selection.InsertAfter ('Item 2');

WordDocument1.Lists.Items (i). Range.Select;

WordApplication1.Selection.Copy;

Тобто ми вставляємо в документ текст першого пункту списку, він потрапляє на своє місце. Потім посилаємо в Word символ переходу рядки, він чесно переходить і тим самим сам створює нам другий пункт списку, куди і вставляємо потрібний рядок. Ну і так далі, потрібну кількість разів. Останні два рядки потрібні, якщо список заготовлено в окремому файлі - після їх виконання список виявляється в буфері обміну. Тут вигода в тому, що можемо мати заготівлі списків різних стилів і по ходу справи вибирати, який список створити. Потім відкриваємо документ, де має бути список, виділяємо за допомогою Range потрібний шматок, копіюємо з буфера обміну через WordDocument1.Range (a, b). Paste. Щоб не зіпсувати файл із заготівлею, можемо відразу після відкриття перезберегти його під іншим ім'ям, а можемо просто вийти з нього без збереження змін

var vsave: OleVariant;

...

vsave: = wdDoNotSaveChanges;

WordDocument1.Close (vsave);

Константа збереження змін може приймати значення

Символьне позначення Шістнадцяткове
wdSaveChanges $ FFFFFFFF
wdDoNotSaveChanges $ 00000000
wdPromptToSaveChanges $ FFFFFFFE

Перше значення зберігає зміни, другий дає можливість вийти без збереження змін. Остання константа викликає при виході стандартний діалог збереження змін. Можемо зробити і дещо по-іншому. Хоча ми не можемо створити новий елемент списку, але текст у вже існуючому змінити можна:

var i, j: Integer;

...

i: = 1;

j: = 1;

WordDocument1.Lists.Item (i). ListParagraphs.Item (j). Range.Text: = 'Item 1';

Так що можна з допомогою переходів рядка створити потрібну кількість елементів, а потім їх заповнити:

WordDocument1.Lists.Item (i). Range.Select;

WordApplication1.Selection.Collapse (vcol);

WordApplication1.Selection.InsertAfter (# 13);

j: = 1;

WordDocument1.Lists.Item (i). ListParagraphs.Item (j). Range.Text: = 'Item 1';

j: = 2;

WordDocument1.Lists.Item (i). ListParagraphs.Item (j). Range.Text: = 'Item 2';

Це було у припущенні, що у нас один елемент списку в заготівлі вже є. Ну ось, загалом-то, і все про текст, списки і малюнки

Статистика документів

У даному невеликому матеріалі розглядається питання підрахунку статистики файлів *. doc і *. rtf. Таке питання у мене виникло, коли довелося зробити невелику базу даних з обліку документів, куди треба було заносити і статистику документа - число знаків, слів і т.п. Відкривати кожного разу Word, підрахункам і забивати її у форму введення було лінь, так що прийшла в голову думка цю справу автоматизувати. Інформації з цього питання знайти так і не вдалося, так що основним джерелом знань служили заголовний файл Word2000.pas і довідка за Visual Basic for Applications. Ну і, звичайно, безліч різних експериментів.

Відразу обмовлюся, що я не професійний програміст, так що в тонкощі інтерфейсів вникати не будемо - сам у них не особливо розуміюся. Тому, не мудруючи лукаво, просто помістимо на формі компоненти WordApplication і WordDocument з палітри Servers. Для роботи використовуються властивості і методи цих компонентів.

Вбудована статистика Word підраховує статистику звичайного тексту, звичайних і кінцевих виносок. Для підрахунку статистики використовується метод компонента WordDocument ComputeStatistic (). Він має один параметр, що характеризує, що саме вважати, що вдає із себе шістнадцяткову константу. Константи описані в заголовному файлі Word2000.pas, він лежить зазвичай в / Delphi / Ocx / Servers.

Шістнадцяткова Символьне позначення Сенс
$ 00000000 wdStatisticWords Кількість слів
$ 00000001 wdStatisticLines Кількість рядків
$ 00000002 wdStatisticPages Кількість сторінок
$ 00000003 wdStatisticCharacters Знаки без пробілів
$ 00000004 wdStatisticParagraphs Кількість розділів
$ 00000005 wdStatisticCharactersWithSpaces Знаки з пробілами

Це було основне, що треба знати. Ну а тепер по порядку.

Помістивши на форму згадані компоненти, бачимо, що властивостей і методів у них зовсім мало. В першу чергу слід визначитися з методом ConnectKind компонента WordApplication. Воно може набувати різних значень, але ми залишимо присвоюються за замовчуванням значення ckRunningOrNew. Це означає, що з'єднання відбувається з вже працюючим сервером, при його відсутності запускається новий. Як правило, це цілком влаштовує.

Насамперед відкриємо документ. Попередньо треба оголосити змінну FileName, вона буде типу OleVariant, якої привласнимо рядок з ім'ям файлу.

WordApplication1.Connect;

WordApplication1.Documents.Open (FileName,

EmptyParam, EmptyParam, EmptyParam,

EmptyParam, EmptyParam, EmptyParam,

EmptyParam, EmptyParam, EmptyParam,

EmptyParam, EmptyParam);

WordDocument1.ConnectTo (WordApplication1.ActiveDocument);

Зверніть увагу на кількість параметрів-"пустушок". Їх число більше того, яке звичайно приводиться в книжках. Ну, в моїх, у всякому разі. Пояснюється це тим, що "книжкові" функції призначені для MS Word 97, а такий запис для роботи з Word 2000 і Word XP.

"Plain Text"

Оголосивши потрібну кількість змінних типу LongInt (в дуже великому файлі або при підсумовуванні по декількох документах в принципі може виявитися більше знаків, ніж межі звичайного цілого типу), можемо вже і приступати до підрахунку. Наприклад, порахуємо кількість слів, знаків з пробілами та без пробілів звичайного тексту, а також кількість сторінок у документі. Результати збережемо відповідно в "довгих" змінних WCount, SCount, CCount, і PCount.

WCount: = WordDocument1.ComputeStatistics ($ 00000000);

CCount: = WordDocument1.ComputeStatistics ($ 00000003);

SCount: = WordDocument1.ComputeStatistics ($ 00000005);

PCount: = WordDocument1.ComputeStatistics ($ 00000002);

Відкривши потрібний документ у Word'е і викликавши діалог підрахунку статистики, неважко побачити, що значення змінних рівні параметрами вордівський статистики зі скинутим прапорцем "Враховувати всі виноски".

Виноски

Посилання у документах можуть бути звичайні і кінцеві. Тобто якщо перші розташовуються внизу цієї сторінки, то кінцеві - строго в кінці документа. Крім того, вони можуть відрізнятися і нумерацією - автоматичною або заданої користувачем. Почнемо зі звичайних виносок як з самого простого. У термінології об'єктної моделі Word - Footnotes. Спочатку треба обчислити кількість самих виносок:

ifcount: = WordDocument1.DefaultInterface.Footnotes.Count;

Підрахунок статистики тексту у виносці проводиться так:

FWCount: = WordDocument1.DefaultInterface.Footnotes.Item (ifoot). Range.ComputeStatistics ($ 00000000);

Тут ifoot - ціле число, "Нумер" виноску. Для того, щоб врахувати самі номери виносок, зробимо так:

FWCount: = FWCount + WordDocument1.DefaultInterface.Footnotes.Item (ifoot). Reference.ComputeStatistics ($ 00000000);

Це ми порахували для прикладу кількість слів у виносці з номером ifoot і її мітці - при користувача нумерації в якості "номери" може бути ціле речення. Далі починаємо перебирати їх одну за одною. При цьому слід врахувати, що крім статистики виносок необхідно отримати і статистику їх "номерів". Тобто:

for ifoot: = 1 to ifcount do begin

FWCount: = FWCount + WordDocument1.DefaultInterface.Footnotes.Item (ifoot). Range.ComputeStatistics ($ 00000000);

FCCount: = FCCount + WordDocument1.DefaultInterface.Footnotes.Item (ifoot). Range.ComputeStatistics ($ 00000003);

FSCount: = FSCount + WordDocument1.DefaultInterface.Footnotes.Item (ifoot). Range.ComputeStatistics ($ 00000005);

FCCount: = FCCount + WordDocument1.DefaultInterface.Footnotes.Item (ifoot). Reference.ComputeStatistics ($ 00000003);

FSCount: = FSCount + WordDocument1.DefaultInterface.Footnotes.Item (ifoot). Reference.ComputeStatistics ($ 00000005) +1;

if WordDocument1.DefaultInterface.Footnotes.Item (ifoot). Reference.TextIntToStr (ifoot)

then begin

FWCount: = FWCount +

WordDocument1.DefaultInterface.Footnotes.Item (ifoot). Reference.ComputeStatistics ($ 00000000);

end;

end;

Додаток одиниці з'являється від того, що сума статистики виносок і номерів не збігається з тим, що видає вбудована статистика Word. Між номером виноски і текстом виноски Word ставить пробіл, який чомусь не враховується. Умовний оператор визначає, як пронумерована дана виноска - за умовчанням чи ні. В останньому випадку слід перевірити кількість слів у позначенні виноски. Така схема дає результат, що збігається зі свідченнями вбудованої статистики. Крім того, цикл у нас йде від 1 - так починається нумерація виносок в MS Word, та й практично всіх інших об'єктів теж.

Тепер перейдемо до кінцевим виносок. Теоретично все те ж саме, тільки замість слова "Footnotes" пишемо "Endnotes". І тут натрапляємо на сюрприз - чомусь вона вважає неточно. Я в даному випадку поступив так: зберігаю документ під іншим ім'ям, переконвертірую кінцеві виноски в звичайні і далі все, як сказано вище. Збереження документа:

WordDocument1.SaveAs (FileName, FileFormat),

де в дужках стоять два параметри типу OleVariant - ім'я файлу і шістнадцяткова константа, що задає формат файлу. Деякі константи:

Шістнадцяткова Символьне позначення Сенс
$ 00000000 wdFormatDocument Документ Word
$ 00000004 wdFormatDOSText Простий текст
$ 00000006 wdFormatRTF Файл RTF

Повний список констант формату можна знайти все в тому ж файлі Word2000.pas. І ще один цікавий момент - якщо просто поставити в дужки обидві константи, працювати не буде. Слід попередньо оголосити два змінних, присвоїти їм відповідні значення і тільки потім зберігати.

Ну, а тепер, власне, можемо повернутися до виносок. Конвертування кінцевих виносок на звичайні відбувається так:

WordDocument1.DefaultInterface.Endnotes.Convert;

Тепер ми маємо документ, в якому містяться лише звичайні виноски. З ними жодних проблем не виникає, приклад, як з ними працювати, див. вище. Якщо цікавить статистика окремо різних типів виносок, вважаємо попередньо статистику звичайних виносок, зберігаємо її в "буферних" змінних і вважаємо ще раз після конвертації. Різниця дасть статистику кінцевих виносок окремо. Склавши статистику виносок і простого тексту, отримуємо статистику документа з урахуванням виносок так, як її дає сам Word.

Додатково ...

Тут за традицією кілька покритикуємо Microsoft. Як виявилося, Word показує не все, що міститься в документі. Не приймаються в розрахунок колонтитули. Адже в них може міститися неабиякий шматок тексту, особливо у довідках, бланках і т.п. Виявляється, Word їх насправді вважає, але нам не показує. От і подивимося, як же його можна змусити це зробити.

Колонтитули в документі тісно пов'язані з дещо загадковою штукою під назвою "розділи" - Sections. Кожен розділ може мати верхні та нижні колонтитули. Тому першою справою визначаємо кількість абзаців.

isectct: = WordDocument1.DefaultInterface.Sections.Count;

Тут у нас цілі змінні isectct, icofct, icohct позначають відповідно кількість розділів як таких, кількість нижніх і верхніх колонтитулів даного розділу. Змінна isec служить "номером" розділи, змінні icof, icoh "нумерують" відповідно нижні і верхні колонтитули в межах даного розділу. Кількість колонтитулів у розділі визначаємо так:

icofct: = WordDocument1.DefaultInterface.Sections.Item (isec). Footers.Count;

icohct: = WordDocument1.DefaultInterface.Sections.Item (isec). Headers.Count;

Тепер вже можемо "дістати" текст з колонтитула:

CBWCount: =

WordDocument1.DefaultInterface.Sections.Item (isec). Footers.Item (icof). Range.ComputeStatistics ($ 00000000);

У даному випадку ми для прикладу порахували кількість слів, що містяться в нижньому колонтитулі під номером icof, що належить розділу під номером isec. Тепер можемо написати "подвійної" цикл для підрахунку статистики верхніх і нижніх колонтитулів. Повністю це буде виглядати так:

isectct: = WordDocument1.DefaultInterface.Sections.Count;

for isec: = 1 to isectct do begin

icofct: = WordDocument1.DefaultInterface.Sections.Item (isec). Footers.Count;

icohct: = WordDocument1.DefaultInterface.Sections.Item (isec). Headers.Count;

for icof: = 1 to icofct do begin

CBWCount: = CBWCount +

WordDocument1.DefaultInterface.Sections.Item (isec). Footers.Item (icof). Range.ComputeStatistics ($ 00000000);

CBCCount: = CBCCount +

WordDocument1.DefaultInterface.Sections.Item (isec). Footers.Item (icof). Range.ComputeStatistics ($ 00000003);

CBSCount: = CBSCount +

WordDocument1.DefaultInterface.Sections.Item (isec). Footers.Item (icof). Range.ComputeStatistics ($ 00000005);

end;

for icoh: = 1 to icohct do begin

CHWCount: = CHWCount +

WordDocument1.DefaultInterface.Sections.Item (isec). Headers.Item (icoh). Range.ComputeStatistics ($ 00000000);

CHCCount: = CHCCount +

WordDocument1.DefaultInterface.Sections.Item (isec). Headers.Item (icoh). Range.ComputeStatistics ($ 00000003);

CHSCount: = CHSCount +

WordDocument1.DefaultInterface.Sections.Item (isec). Headers.Item (icoh). Range.ComputeStatistics ($ 00000005);

end;

end;

У змінних, до яких на кожному кроці додаються результати статистики, після перебору всіх розділів накопичиться сумарна статистика слів, знаків з пробілами і знаків без пробілів у всіх колонтитулах.

Часто використовуються для малювання схемок текстові вставки з панелі малювання також представляють інтерес. Сам Word формально вважає їх "картинками", які не мають жодної статистики - мабуть, за географічним розташуванням в панелі інструментів. У об'єктної моделі - Shapes. Ось тут починається найцікавіше. По-перше, все, що знаходиться на панелі малювання, є Shapes. Тобто в принципі для Word'а усі були одно, текстова вставка, об'єкт WordArt або геометрична фігура. Разом з тим виглядає досить нелогічно, що цей самий Shape можна переконвертувати, на вибір, у Frame або InlineShape. Вони вже мають статистикою, так що, здавалося б, все в порядку. Але підступності Microsoft, здається, взагалі немає межі. По-перше з подивом виявляємо, що Shapes нумеруються індексом типу OleVariant. Що з ним далі робити, незрозуміло. Якщо просто привласнювати індексом ціле число, при конвертації кожного другого Shape під Frame отримуємо помилку. А якщо обробити виняток, то будемо таки мати статистику половини вставок. Мабуть, є якісь тонкощі з парними і непарними індексами. По-друге, InlineShape штука і зовсім загадкова. Ніяких помилок при конвертації не виникало, але й кількість InlineShapes незмінно виявлялося нульовим. Підрахувати статистику вставок вдалося тільки зберігши файл як RTF і розколупавши його код, але це варто описати окремо. Наводився ж останній абзац в надії, що хтось з таким стикався і знайшов спосіб роботи з Shapes "вбудованими" способами.

Ну, ось практично і все. Підсумовуючи все, що ми отримали, маємо статистику документа навіть точніше вбудованої. Ще пара зауважень. Перед підрахунком Word стоїть "сховати", щоб він не маячила на екрані:

WordApplication1.Visible: = False;

При підрахунку статистики, особливо якщо в документі міститься щось окрім простого тексту, вважається, що у файл внесені зміни. Тому наостанок зберігаємо і закриваємо документ:

WordDocument1.Save;

WordDocument1.Close;

Ну і, звичайно, робимо сервера Word Disconnect, коли він стане нам вже не потрібен.

А тепер попередження тим, хто зацікавився даним питанням і хоче поекспериментувати сам. Офіс занадто тісно пов'язаний з Windows, тому на збої в його роботі система реагує вкрай гостро. При налагодженні програм підрахунку статистики у мене після помилки часто з'являвся "блакитний екран". Те ж саме відбувалося, якщо після розбору RTF - файлу у пошуках Shapes і перетворення їх на звичайний текст у Word завантажувався неправильно "зібраний" файл. Так що дуже рекомендується попередньо зберегти важливі дані або поставити систему надійніше. У мене стоїть WindowsXP, який до таких збоїв виявився нечуствітелен. Крім того, поки наведене тут не було налагоджено, після помилок частенько летів сам офіс. Так що майте під рукою дистрибутив для запуску діагностики офісу і усунення пошкоджень.

Працюємо з таблицями

Кожен, напевно, хоч раз стикався з необхідністю видачі звіту. У Delphi є для цього спеціальні компоненти, але вони накладають на нас досить суворі обмеження на форму представлення даних. Одним з виходів може бути використання програми MS Word. Тут не будемо докладно обговорювати найпростіше запитання, як відкрити документ та додати в нього потрібний рядок тексту, це є практично в кожному підручнику з Delphi, наведемо тільки самі необхідні відомості. А з літератури на цю тему особливо рекомендується знайти книжку А.Я. Архангельського "Мова SQL у Delphi 5". Але що може надати звіту таку читабельність, як представлення результатів у систематизованому табличному вигляді? У цій статті і обговорюється питання програмної роботи з таблицями документа Word.

Тут можуть бути два шляхи. Перший - якщо ми знаємо заздалегідь структуру даних звіту, можемо приготувати шаблон, куди в елементи таблиці потім просто занесемо потрібні дані. І другий - створюємо звіт з нуля, малюємо в документі таблицю, заповнюємо її. При цьому ми можемо програмно додати або видалити рядки і стовпці, об'єднати чи розбити осередку - майже все, що ми робимо в самому Word'e. Все, що знадобиться - компоненти WordApplication і WordDocument з палітри Servers

Тепер все по порядку - відкриваємо файл і приступаємо. Попередньо оголошуємо змінну FileName, типу OleVariant, якої присвоюємо рядок з ім'ям файлу.

WordApplication1.Connect;

WordApplication1.Documents.Open (FileName,

EmptyParam, EmptyParam, EmptyParam,

EmptyParam, EmptyParam, EmptyParam,

EmptyParam, EmptyParam, EmptyParam,

EmptyParam, EmptyParam);

WordDocument1.ConnectTo (WordApplication1.ActiveDocument);

Зверніть увагу на кількість параметрів - "пустушок". Їх кількість не збігається з тим, що звичайно приводиться в книжках. Пояснюється це тим, що "книжкова" функція призначена для MS Word 97, а такий запис для Word 2000 і Word XP.

Створення нового документа виглядає простіше:

WordApplication1.Connect;

WordApplication1.Documents.Add (EmptyParam, EmptyParam, EmptyParam, EmptyParam);

WordDocument1.ConnectTo (WordApplication1.ActiveDocument);

Тут також ставимо на пару "пустушок" більше - з тих же самих причин. Крім того, корисно буде відразу ж відключити перевірку орфографії, щоб Word не витрачав час даремно:

WordApplication1.Options.CheckSpellingAsYouType: = False;

WordApplication1.Options.CheckGrammarAsYouType: = False;

Після закінчення роботи нам треба зберегти або роздрукувати наш звіт:

WordDocument1.PrintOut;

WordDocument1.SaveAs (FileName);

де змінна в дужках типу OleVariant, їй присвоюємо рядок з ім'ям файлу.

Об'єкт Range

У документі нас поки що більше всього цікавить об'єкт Range, який нам знадобиться при створенні таблиці. Він представляє з себе шматок тексту, який може включати в себе як весь текст документа, так і будь-яку його частину. Тобто:

var range1, range2, range3, a, b: OleVariant;

...

range1: = WordDocument1.Range;

a: = 5;

b: = 15;

range2: = WordDocument1.Range (a, b);

range3: = WordDocument1.Range (a);

Перший наш об'єкт включає в себе весь текст документа, у другого ми обмежили межі 5-м і 15-м символами, третій представляє з себе весь подальший текст документа, починаючи з 5-го символу.

Об'єкт має кілька корисних методів, наприклад, з його допомогою можемо додати текст в документ:

range2.InsertAfter ('MS Word');

Це ми вставили текст після виділеного Range. Точно також можемо вставити текст і перед ним, для цього служить метод InsertBefore (). Текст, укладений в об'єкті Range, можемо отримати так:

WordDocument1.Range (a, b). Text;

Крім того, за допомогою Range можемо змінити шрифт в межах об'єкта.

Приклад:

a: = 5;

b: = 15;

WordDocument1.Range (a, b). Font.Bold: = 1;

Якщо хочемо скасувати виділення жирним шрифтом, присвоюємо 0. Аналогічно можна зробити шрифт курсивом, підкресленим - наберіть WordDocument1.Range.Font., І середовище сама підкаже, які можуть бути варіанти. Методи Select, Cut, Copy і Paste працюють як у звичайному тексті. За допомогою Paste можемо на місце вибраного Range вставити не лише рядки, але й малюнок, що знаходиться в буфері обміну.

Т а б л і ц и

Робота зі стовпцями, рядками і осередками

Таблиці в документі Word утворюють колекцію Tables. Їх кількість можемо дізнатися так:

tcount: = WordDocument1.Tables.Count;

до окремої таблиці звертаємося по її номеру:

i: = 1;

WordDocument1.Tables.Item (i) ...,

де i - ціле число. У даному випадку ми звертаємося до першої таблиці, а взагалі i може набувати значення від 1 до WordDocument1.Tables.Count. Якщо нам необхідно створити таблицю самим, слід вчинити так:

WordDocument1.Tables.Add (WordDocument1.Range, i, j, EmptyParam, EmptyParam);

Ця таблиця - єдине, що буде в документі, так як вона замінює собою зазначений у числі параметрів об'єкт Range. У даному випадку одержуємо таблицю на i рядків і j стовпців. Якщо вже еcть якийсь текст, який треба зберегти, абсолютно аналогічним чином можемо вказати межі об'єкта Range:

a: = 5;

b: = 15;

WordDocument1.Tables.Add (WordDocument1.Range (a, b), i, j, EmptyParam, EmptyParam);

Змінні a і b мають бути оголошені як OleVariant.

Ну от, тепер у нас є таблиця. Неважливо, містилася вона вже в документі або ми створили її самі. Подивимося, що ж ми з нею можемо зробити. Кількість стовпців і рядків дізнаємося так:

i: = 1;

k: = WordDocument1.Tables.Item (i). Columns.Count;

j: = WordDocument1.Tables.Item (i). Rows.Count;

Тут ми знову звернулися до першої таблиці, але можемо працювати з будь-який - треба лише правильно вказати її номер. Тепер змінимо ширину стовпців або висоту рядків:

WordDocument1.Tables.Item (i). Columns.Width: = 90;

WordDocument1.Tables.Item (i). Rows.Height: = 45;

Аналогічно можемо задавати розміри окремих рядків і стовпців:

WordDocument1.Tables.Item (i). Columns.Item (j). Width: = 90;

WordDocument1.Tables.Item (i). Rows.Item (j). Height: = 45;

Тут j - знову таки ціле число, починається від 1. Можемо звернеться до окремої клітинки, прочитати або змінити міститься в ній текст:

WordDocument1.Tables.Item (i). Cell (j, k). Range.Text;

Тут j і k цілі змінні, змінюються від 1 до числа рядків або стовпців відповідно. Привласнивши даній величині рядковий вираз, побачимо, що воно з'явилося в осередку (j, k). Трохи незвично, але в таблицях Word на першому місці стоїть саме номер рядка. Можемо також задати програмно відступи від краю осередків, як для всієї таблиці відразу, так і для окремої комірки:

WordDocument1.Tables.Item (i). TopPadding: = 10;

WordDocument1.Tables.Item (i). BottomPadding: = 10;

WordDocument1.Tables.Item (i). RightPadding: = 10;

WordDocument1.Tables.Item (i). LeftPadding: = 10;

У даному випадку ми задали однакові відступи для всієї таблиці, але аналогічні чотири властивості є і у окремої клітинки. Виділити потрібну клітинку, стовпець або рядок можемо наступним чином:

WordDocument1.Tables.Item (i). Cell (j, k). Select;

WordDocument1.Tables.Item (i). Columns.Item (j). Select;

WordDocument1.Tables.Item (i). Rows.Item (j). Select;

Крім того, можемо підігнати розміри осередків за вмістом. Для цього викликаємо метод AutoFit:

WordDocument1.Tables.Item (i). Columns.AutoFit;

Додати рядок або стовпець також не представляє складнощів:

WordDocument1.Tables.Item (i). Columns.Add (EmptyParam);

WordDocument1.Tables.Item (i). Rows.Add (EmptyParam);


Ми додали рядок внизу і стовпець праворуч. Тепер вставимо стовпець у певному місці таблиці:

var i, j: Integer;

varcol: OleVariant;

...

j: = 2;

varcol: = WordDocument1.Tables.Item (i). Columns.Item (j);

WordDocument1.Tables.Item (i). Columns.Add (varcol);

Цілком аналогічно чинимо і з рядками. Взагалі в дужках вказані рядок або стовпець, перед якими відбувається вставка. Проте явно вказати в дужках чомусь не можна, треба через змінну.

Тепер про об'єднання осередків. Досить просто:

WordDocument1.Tables.Item (i). Cell (j, k). Merge (WordDocument1.Tables.Item (i). Cell (j, k +1));

Ми об'єднали дві сусідні по горизонталі комірки (j, k) і (j, k +1). При цьому виходить, що велика клітинка як би має два "адреси". Аналогічно треба діяти і при об'єднанні по вертикалі. Все точно так само, але з нумерацією осередків після об'єднання двох сусідніх по вертикалі починається плутанина і при спробі заповнити таблицю виникають помилки. Тепер розіб'ємо осередки.

varrow: = 1;

varcol: = 2;

WordDocument1.Tables.Item (i). Cell (j, k). Split (varrow, varcol);

Тут ми розбили клітинку (j, k) на дві по горизонталі. Змінні varcol і varrow типу OleVariant, це кількість стовпців і рядків, на які розбивається дана клітинка. Тут знову з нумерацією починається чехарда, так що це питання розбиття та об'єднання осередків представляє скоріше чисто теоретичний інтерес. У таких випадках краще заздалегідь приготувати шаблони.

Тепер для прикладу видалимо з таблиці другий стовпець або третій рядок:

WordDocument1.Tables.Item (i). Columns.Item (2). Delete;

WordDocument1.Tables.Item (i). Rows.Item (3). Delete;

Зовнішній вигляд таблиці

Найпростіша таблиця, звичайно, виглядає не дуже. Тепер подивимося, як ми можемо її прикрасити. При бажанні все зробити посимпатичніше можемо використовувати текстуру. Виглядати це буде так:

WordDocument1.Tables.Item (i). Cell (j, k). Shading.Texture: = wdTexture20Percent;

Цілком аналогічно можемо зробити текстуру в цілому стовпці або рядку:

WordDocument1.Tables.Item (i). Columns.Item (j). Shading.Texture: = wdTexture20Percent;

WordDocument1.Tables.Item (i). Rows.Item (j). Shading.Texture: = wdTexture20Percent;

Текстура задається шістнадцятковій константою, список констант можна знайти заголовному файлі Word2000.pas. Можна їх використовувати як в шістнадцятковому, так і в символьному вигляді. Щоб не захаращувати матеріал, значення констант будуть виноситися в "Додаток" в кінці статті. Відразу обмовлюся, що заливання буде чорно-біла або в шкалі сірого. Заливання певним кольором поки так і не вдалося виявити. Найперша константа означає відсутність заливки. Її можна використовувати, щоб скасувати текстуру.
Щоб виділити що-небудь важливе, можемо змінити шрифт тексту в певній клітинці. Для цього скористаємося властивостями об'єкта Selection:

WordDocument1.Tables.Item (i). Cell (1,2). Select;

WordApplication1.Selection.Font.Color: = clRed;

WordApplication1.Selection.Font.Italic: = 1;

WordApplication1.Selection.Font.Size: = 16;

У даному прикладі ми зробили колір тексту у клітинці (1,2) червоним, виділили його курсивом і змінили розмір на 16. Крім того, можемо змінити його шрифт підкресленим, перекресленим і т.п.

Ще один спосіб змінити зовнішній вигляд таблиці - використовувати стильові шаблони Word'a. У таблиці є метод AutoFormat, який змінює зовнішній вигляд таблиці відповідно до якимись зумовленими стилями. У заголовному файлі він описаний таким чином:

procedure AutoFormat (var Format: OleVariant; var ApplyBorders: OleVariant;

var ApplyShading: OleVariant; var ApplyFont: OleVariant;

var ApplyColor: OleVariant; var ApplyHeadingRows: OleVariant;

var ApplyLastRow: OleVariant; var ApplyFirstColumn: OleVariant;

var ApplyLastColumn: OleVariant; var AutoFit: OleVariant);

Перший параметр представляє з себе власне константу, задану стиль, а інші показують, чи будуть вимоги нового стилю застосовуватися конкретно до кордонів, тіні, шрифту, кольору, першому рядку, останньому рядку, на одну колонку і останньому стовпцю. Останній параметр у списку вказує, чи треба підганяти розмір осередків по їх вмісту - краще самому потім викликати AutoFit.

Як показала практика, працюють тільки два перших параметра. Всі інші замінюємо "пустушками". Тобто це скоріше буде просто спосіб зміни стилю кордонів, а й на тому спасибі. Деякі стилі таблиць дані в додатку, повний же список шукайте в заголовному файлі. Для прикладу застосуємо до нашої таблиці стиль "Веб3". Замість другого параметра ставимо варіантну змінну, якої присвоюємо wdTableFormatApplyBorders. Тобто на практиці це виглядає так:

var tformat, tappbrd: OleVariant;

...

tformat: = wdTableFormatWeb3;

tappbrd: = wdTableFormatApplyBorders;

i: = 1;

WordDocument1.Tables.Item (i). AutoFormat (tformat, tappbrd, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,

EmptyParam, EmptyParam, EmptyParam);

І ще про один спосіб створення таблиць

Людям, які цікавляться роботою з MS Word, можливо, теж траплялися в інтернеті компоненти, що перетворюють в таблицю відповідним чином відформатований текст. Ось ми якраз і розберемося, як же вони влаштовані. Тут нам знову треба згадати про об'єкт Range, а саме про наявний у нього метод ConvertToTable. У заголовному файлі це виглядає так:

function ConvertToTable (var Separator: OleVariant; var NumRows: OleVariant;

var NumColumns: OleVariant; var InitialColumnWidth: OleVariant;

var Format: OleVariant; var ApplyBorders: OleVariant;

var ApplyShading: OleVariant; var ApplyFont: OleVariant;

var ApplyColor: OleVariant; var ApplyHeadingRows: OleVariant;

var ApplyLastRow: OleVariant; var ApplyFirstColumn: OleVariant;

var ApplyLastColumn: OleVariant; var AutoFit: OleVariant;

var AutoFitBehavior: OleVariant; var DefaultTableBehavior: OleVariant)

Тут знову бачимо все ті ж константи застосування стилю, що і в Автоформат. Тільки на відміну від нього тут вони помилок не викликають. Правда, є в мене страшне підозра, що вони все одно не працюють і можемо зі спокійною совістю поставити замість них "пустушки" - всіх, крім знову-таки, перших двох параметрів "застосування змін". Тепер по порядку. Перший параметр у нас задає символ, яким будуть відокремлюватися осередки одного рядка нашої майбутньої таблиці, другий - кількість рядків таблиці, третій - число стовпців, потім йде ширина стовпців. Наступна група параметрів задає стиль таблиці та особливості його застосування, необхідні значення констант є в таблиці "Програми". Останні три параметри задають підгонку розміру осередків по вмісту, але насправді не працюють. Так що ставимо замість них EmptyParam. І, нарешті, практичний приклад. Припустимо, ми відкрили новий документ і занесли в нього потрібний текст:

WordDocument1.Range.InsertAfter ('column1');

WordDocument1.Range.InsertAfter (# 9);

WordDocument1.Range.InsertAfter ('column2');

WordDocument1.Range.InsertAfter (# 9);

WordDocument1.Range.InsertAfter ('column3');

WordDocument1.Range.InsertAfter (# 9);

WordDocument1.Range.InsertAfter ('column4');

WordDocument1.Range.InsertAfter (# 13);

Таку операцію повторимо тричі, і у нас буде заготівля для таблиці на 4 шпальти і 3 рядки. Майбутні стовпці відокремлюються символами табуляції, а рядки - переходами на новий рядок. Тепер виділяємо об'єкт Range - в даному випадку це весь текст документа, і перетворюємо їх у таблицю:

var tsepar, tnumrows, tnumcols, tincolw, tformat,

tappbrd, tappshd, tappfnt, tappclr, tapphr, tapplr,

tappfc, tapplc: OleVariant;

...

tsepar: = wdSeparateByTabs;

tnumrows: = 3;

tnumcols: = 4;

tincolw: = 150;

tformat: = wdTableFormatNone;

tappbrd: = wdTableFormatApplyBorders;

tappshd: = wdTableFormatApplyShading;

tappfnt: = wdTableFormatApplyFont;

tappclr: = wdTableFormatApplyColor;

tapphr: = wdTableFormatApplyHeadingRows;

tapplr: = wdTableFormatApplyLastRow;

tappfc: = wdTableFormatApplyFirstColumn;

tapplc: = wdTableFormatApplyLastColumn;

WordDocument1.Range.ConvertToTable (tsepar, tnumrows, tnumcols, tincolw, tformat,

tappbrd, tappshd, tappfnt, tappclr, tapphr, tapplr,

tappfc, tapplc, EmptyParam, EmptyParam, EmptyParam);

Загалом-то, ми можемо задавати тільки перші шість параметрів, а всі інші замінити на "пустушки". Єдине, що тут новеньке, це параметр "роздільник". У даному випадку в якості роздільника буде використовуватися символ табуляції. Інші варіанти дивіться в останній таблиці "Додатки", але мені здається, особливої ​​практичної користі від них немає.
Виконавши все це, виявляємо, що наш текст перетворився в таблицю. Все це трохи нагадує створення таблиць в HTML.

Програми

Список деяких констант. Дивіться файл Word2000.pas

Опис Символьне позначення Шістнадцяткове
Текстури
Деякі константи текстур - відкрийте Word2000.pas в "блокноті", введіть у діалог пошуку "texture", і отримаєте повний список.
wdTextureNone $ 00000000
wdTexture2Pt5Percent $ 00000019
wdTexture7Pt5Percent $ 0000004B
wdTexture35Percent $ 0000015E
wdTexture62Pt5Percent $ 00000271
wdTextureSolid $ 000003E8
wdTextureDarkHorizontal $ FFFFFFFF
wdTextureCross $ FFFFFFF5
Формат таблиці
Константи формату таблиці. Необхідні при використанні автоформату і перетворенні тексту в таблицю.
wdTableFormatNone $ 00000000
wdTableFormatSimple1 $ 00000001
wdTableFormatSimple3 $ 00000003
wdTableFormatClassic1 $ 00000004
wdTableFormatClassic3 $ 00000006
wdTableFormatColorful1 $ 00000008
wdTableFormatColumns1 $ 0000000B
wdTableFormatGrid1 $ 00000010
wdTableFormatGrid3 $ 00000012
wdTableFormatList1 $ 00000018
wdTableFormat3DEffects1 $ 00000020
wdTableFormat3DEffects2 $ 00000021
wdTableFormat3DEffects3 $ 00000022
wdTableFormatContemporary $ 00000023
wdTableFormatElegant $ 00000024
wdTableFormatProfessional $ 00000025
wdTableFormatSubtle1 $ 00000026
wdTableFormatWeb3 $ 0000002A
Стилі таблиці
Константи "застосування змін" стилю таблиці. В ідеалі передбачається, що можна задавати окремо, чи змінювати стиль кордонів, тексту, кольору і т.д. У автоформат працюють, м'яко висловлюючись, незрозуміло, весь час виникають якісь незрозумілі помилки.
wdTableFormatApplyBorders $ 00000001
wdTableFormatApplyShading $ 00000002
wdTableFormatApplyFont $ 00000004
wdTableFormatApplyColor $ 00000008
wdTableFormatApplyAutoFit $ 00000010
wdTableFormatApplyHeadingRows $ 00000020
wdTableFormatApplyLastRow $ 00000040
wdTableFormatApplyFirstColumn $ 00000080
wdTableFormatApplyLastColumn $ 00000100
Розділювачі
Константи роз'єднувачів для конвертації тексту в таблицю.
wdSeparateByParagraphs $ 00000000
wdSeparateByTabs $ 00000001
wdSeparateByCommas $ 00000002
wdSeparateByDefaultListSeparator $ 00000003
Додати в блог або на сайт

Цей текст може містити помилки.

Програмування, комп'ютери, інформатика і кібернетика | Курсова
75.5кб. | скачати


Схожі роботи:
Програмування для Word з Delphi
Робота з HTTP протоколом в Delphi
Робота з потоками в середовищі Delphi
Робота з Word 98
Робота редактором Word
Робота з таблицями у Word
Робота в програмі Word
Робота в редакторі Word 2000
Microsoft Word Робота з шаблонами
© Усі права захищені
написати до нас