VBA: ответы на вопросы
(оригинал доступен на сайте orlovs.pp.ru)
*   *   *
За последние пять лет мне пришло немало писем с вопросами о решении проблем, возникающих при написании программ на языке Visual Basic for Applications. Несмотря на то, что большинство из них было посвящено конкретным техническим решениям, возможно, они будут интересны и вам, так как демонстрируют практическое применение VBA-программирования. Все эти вопросы - реальные, то есть были заданы пользователями, исходя из необходимости решения возникающих задач.

1.
"В документе я хочу защитить от изменений пользователем только рисунок. Могу ли я это сделать? Метод Protect, похоже, этого сделать не дает."
Нет. Microsoft Word делать это не позволяет.
Впрочем, можно пойти на хитрость. Создайте документ Doc1.doc и вставьте в него рисунок. Затем сохраните документ с рисунком, задав ему пароли на открытие и на изменения. Создайте документ Doc2.doc. В том месте, где должен быть рисунок, вызовите окно Вставка-Обьект-Создание из файла и укажите в пути файл doc1.doc, отметив предварительно пункт "Связь с файлом". Введите пароль на открытие - и рисунок в Вашем документе. Сохраните его.
Теперь при открытии файла doc2.doc рисунок будет виден, но при попытке изменить его будет запрашиваться пароль на открытие файла doc1.doc. Проблема остается в том, что оба файла - и с рисунком, и с текстом - должны присутствовать, причем в тех местах, где они были изначально. То есть вся эта конструкция труднопереносима.

2.
"Возможно ли в Word проводить сравнение двух документов по словам..."
Да, разумеется. Откройте один из сравниваемых документов, выберите пункт меню "Сервис"-"Исправления"-"Сравнить версии" и выберите в открывшемся диалоговом окне второй файл для сравнения. Все разночтения будут выделены, в зависимости от их характера - зачеркиванием, цветом и др.

3.
"Как можно узнать количество страниц в Word2000 из макроса?"
С помощью команды
p = ActiveDocument.ComputeStatistics(wdStatisticPages)
где в переменную p запишется количество страниц в активном документе.

4.
"Мне необходимо из программы на VBA в Word открыть стандартное диалоговое окно выбора файлов и после считать результат выбора. Как это можно сделать - с помощью API?"
Для того, чтобы выбрать файлы, необязательно использовать именно API. Достаточно стандартных диалоговых окон Word. Их выпадающий список можно получить, набрав в Редакторе VBA фразу "Dialogs(". Выбрать файл позволяет, к примеру, окно, вызываемое константой wdDialogFileOpen - для его вызова можно использовать такой код:
With Dialogs(wdDialogFileOpen)
.Display
vibfail = .FileName
End With
Команда .Display отображает диалоговое окно, а следующая строчка записывает в переменную имя выбранного файла. При этом открытия выбранного файла не происходит (если надо, чтобы происходило, следует вместо команды .Display использовать команду .Show). Подробнее - смотрите Справку VBA по слову Dialogs и раздел "Displaying built-in Word dialog boxes."
В Microsoft Excel аналогичное действие выполняется значительно проще - командой file = Application.GetOpenFilename. В результате ее выполнения будет отображено окно открытия файла, а после выбора имя файла поместится в переменную (здесь - "file").

5.
"Сделал документацию на свою VBA-программу в Word 97 в doc-файле. Включил в нее screenshot'ы, на которые наложил автофигуры Word - выноски, стрелки, скобки, надписи и проч., что разъясняло бы назначение частей рисунков. Теперь хочется поставлять документацию в формате HTML, но... при конвертации Word начисто игнорирует свои же автофигуры, оставляя в итоговых gif-файлах чистый рисунок. Как цивилизовано выйти из ситуации?"
Да, автофигуры Word97 при конвертации в HTML игнорируются. Для реализации желаемой Вами задачи выделите все автофигуры рисунка вместе с самим рисунком (инструментом "Выделение обьектов" панели "Рисование"), сгруппируйте их, вырежьте в Буфер обмена, а затем вставьте то, что в буфере, на то место, где был исходный рисунок, с помощью команды "Правка"-"Специальная вставка", используя в качестве формата вставляемого изображения "Точечный рисунок" или "Метафайл Windows", т.е. что угодно, кроме "рисунка MS Office". После этого у Вас в документе появится рисунок с всеми вставленными автофигурами, который, однако, спокойно конвертируется в GIF-формат при конвертации всего документа в HTML. Так следует поступить со всеми рисунками в документе. В Word2000 и Word2002 такой проблемы нет - там автофигуры сохраняются в самой генерируемой web-странице, но при просмотре ее в старых браузерах могут быть не видны.

6.
"Как определить с помощью макроса в документе Word текущий номер страницы, где произошло при поиске вхожение заданной подстроки."
Существуют функции Selection.Information(wdActiveEndPageNumber), которая возвращает номер страницы по счету, на которой располагается конец выделения, и функция Selection.Information(wdActiveEndAdjustedPageNumber), которая возвращает присвоенный номер страницы, на которой располагается выделенный фрагмент. Вторую функцию следует использовать тогда, когда необходимо получить тот номер страницы, который указан на ней непосредственно (т.е. с учетом ручных установок нумерации), а первую - если номер необходим абсолютный. Описание обеих команд можно получить в Справке VBA по слову Information.
При работе подпрограммы поиска каждое вхождение выделяется. Вот, к примеру, фрагмент кода макроса, который отображает в диалоговом окне номера страниц, на которых найден текст "text".
Selection.HomeKey Unit:=wdStory
Dim a As String
a = ""
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "text"
.Forward = True
.Wrap = wdFindStop
End With
While Selection.Find.Execute = True
a = a + " " + Str(Selection.Information(wdActiveEndPageNumber))
Wend
MsgBox a

7.
"Открыт документ Word, хочу запустить в нем макрос, который в свою очередь запускает макрос Excel, обрабатывающий Excel-таблицу. После этого через Clipboard из Excel макрос пересылает в Word-документ заданную прямоугольную область таблицы. Макрос Word обрабатывает эту область и начинает в требуемой последовательности копировать в Word-документ через Clipboard фрагменты Excel-таблицы. По окончании копирования Word закрывает все ненужные макросы, включая макрос Excel. Как все это сделать, чтобы работало?"
Для работы из одного приложения Office с другим лучше всего использовать технологию ActiveX. Она основана на имеющейся в Office возможности представлять одну программу в другой как некий обьект, с которым можно работать теми же командами, что используются при непосредственной работе с этой программой.
Так, чтобы можно было из Word'ового макроса работать с Excel'ем, следует создать обьект Excel.Sheet (здесь "es" - простое наименование переменной, у вас может быть любым).
Dim es As Object
Set es = CreateObject("Excel.Sheet")
(Если надо сразу открыть какой-либо файл Excel'а, то можно использовать команду GetObject:
Set es= GetObject("Путь к файлу Excel'а"))
При желании можно сделать созданный обьект Excel видимым:
es.Application.Visible = True
Теперь можно этому обьекту es (т.е. просто запущенному Excel'у) посылать команды такие же, как и в макросах Excel'а (предваряя текстом "es.Application." те из команд, которые не требуют прямого указания обьекта, - так как надо дать понять программе, что работа идет именно с Excel'ем). Так, чтобы открыть файл Excel'а, можно также дать команду
es.Application.Workbooks.Open FileName:="Путь к файлу Excel'а"
а чтобы, например, поместить в первую ячейку открытой книги текст, используйте команду
es.Cells(1, 1).Value = "Это столбец A, строка 1"
В принципе я бы вам посоветовал поместить тот макрос, который Вы планировали для Excel'а, именно в исходный Word'овый, переписав его команды в соответствии с принципом связывания (т.е. управления одним приложением из другого - так, как описано выше).
Закрыть Excel можно командой
es.Application.Quit
Set es= Nothing
Если работать с таблицей из Word почему-либо нельзя, и требуется именно вызвать Excel'евский макрос, то для вызова макроса следует использовать команду
es.Application.Run "имя макроса"
Также можно автоматически запустить какой-либо макрос при открытии файла Excel:
es.Application.Workbooks.Open FileName:="Путь к файлу Excel'а!имя макроса" (например, es.Application.Workbooks.Open FileName:="c:\book1.xls!macr1", точно так же, разделяя имя файла и имя макроса восклицательным знаком - и в команде Shell)
В общем, есть простор для творчества. Про работу из Word'а с Excel'ем и т.д. почитайте разделы Справки VBA: "Работа с приложениями", "Функция CreateObject", "Функция GetObject", "Программирование объектов".

8.
"Можно ли в Word при помощи гиперссылки вызвать команду меню, в частности команду "Найти"?"
Непосредственно с помощью гиперссылки - нет. Но можно поместить текст гиперссылки в элемент формы, который уже связать с макросом, вызывающим диалоговое окно. Для реализации данного способа необходимо вывести на экран панель инструментов "Элементы управления", включить кнопкой "Режим Конструктора", добавить элемент "Надпись", в меню правой кнопки мыши выбрать "Свойства", в разделе Caption поместить текст ссылки, оформить шрифт и цвет текста в соответствующем разделе Свойств, затем из меню правой кнопки мыши выбрать "Исходный текст", а в появившийся макрос вписать команду
Private Sub Label1_Click()
On Error Resume Next
Dialogs(wdDialogEditFind).Show
End Sub
или любые другие, какие пожелаете. После того, как Вы отключите Режим конструктора, созданная надпись с гиперссылкой будет работать так, как Вы желаете - при нажатии на нее вызовется окно поиска текста.
"Я сделал так, как Вы сказали, но при вводе в появляющееся окно поиска фрагмента, которого в тексте нет, не отображается сообщение о безрезультатности поиска - как при использовании непосредственно команды "Найти". Можно ли сделать так, чтобы вызываемое окно работало точь-в-точь так же, как и обычное?"
К сожалению, с командой Dialogs... ничего сделать нельзя - так уж будет себя вести это диалоговое окно.
Однако можно использовать "финт ушами". В VBA есть функция SendKeys, которая передает активному окну нажатия клавиш - как если бы они были нажаты на клавиатуре. (Подробнее - см.справку.) Поэтому можно ее использовать:
Private Sub Label1_Click()
SendKeys "^f"
End Sub
предполагая, что комбинация клавиш Ctrl+f вызывает окно "Найти", как, впрочем, устанавливается по умолчанию. Список кодов функциональных клавиш - в Справке.
Если Вы используете функцию SendKeys, то вызванное ею окно будет вести себя абсолютно так же, как при ручном вызове. Однако помните, что если пользователь переопределит заложенную Вами в макрос комбинацию клавиш, то Ваша программа начнет работать некорректно.

9.
"Как в Excele вставленную на первый лист кнопку приспособить для просмотра и печати следующего или (3,4,5,или конкретного) листа книги?"
В Режиме конструктора (вызывается нажатием соответствующей кнопки на панели инструментов "Элементы управления") щелчком на вставленной кнопке следует войти в Редактор VBA и в качестве обработчика события клика ввести такой код:
Private Sub CommandButton1_Click()
(т.е. то, что должно произойти при клике на кнопке CommandButton1)
ActiveWorkbook.Sheets(2).PrintPreview
(Предварительный просмотр второго активной книги)
ActiveWorkbook.Sheets(2).PrintOut
(Вывод на печать с настройками по умолчанию второго листа активной книги)
End Sub
Вместо второго листа можно поставить третий, четвертый и т.д., соответственно поменяв его номер в параметре Sheets(). Чтобы получить номер того листа, на котором находится кнопка, можно использовать команду ActiveSheet.Index, а чтобы номер следующего - соответственно команду ActiveSheet.Index+1, которые следует подставлять в параметр Sheets(): ActiveWorkbook.Sheets(ActiveSheet.Index+1).PrintPreview.

10.
"Я создал новый ToolBar с помощью макроса и с момента создания такой панели до сих пор не могу найти команду которая бы удержала бы кнопку которой присвоен макрос в утопленном состоянии при клике и отжимала ее при повторном клике."
Это делается с помощью фрагмента кода:
Set myControl = CommandBars("Мои макросы").Controls(1)
With myControl
If .State = msoButtonUp Then .State = msoButtonDown Else .State = msoButtonUp
End With
где "Мои макросы" - имя Вашей панели, а цифра в скобках после Controls - номер кнопки на этой панели, соответственно, тот, который нужная кнопка имеет.
Все функции работы с панелями инструментов, кнопками, выпадающими меню, все тонкости их создания и использования подробно описаны в Справке VBA в разделе "Using Command Bars". В частности, затронутый Вами вопрос освещен в разделе "Adding and modifying toolbars". Попасть в эти разделы Вы можете с помощью системы поиска Справки VBA.

11.
"как вызвать Windows стандартное диалоговое окно открытия-сохранения файла, потому что аналогов как я понимаю в VBA нет."
Ну почему же - нет? В Word окно открытия файла можно вызвать командой
Dialogs(wdDialogFileOpen).Show
а окно сохранения - командой
Dialogs(wdDialogFileSaveAs).Show
В обоих случаях будут вызваны соответствующие окна и выполнены соответствующие действия - открытие файла, его сохранение.
Данные команды возвращают параметры: -2 - если нажато "Закрыть", -1 - если "Ок", 0 - если "Отмена": код
If Dialogs(wdDialogFileOpen).Show = 0 Then Exit Sub
осуществит выход из программы, если в окне выбора файла будет нажата кнопка отмены.
Данные команды можно использовать и не только по "прямому" назначению - для открытия или сохранения файлов. Так, если вместо метода Show использовать Display, то окно отображаться будет, а связанное с ним действие не выполнится. Это позволяет использовать такие окна для выбора файлов с целью какого-либо действия над ними. Например, код
With Dialogs(wdDialogFileOpen)
.Display
asdf = .Name
End With
даст возможность пользователю выбрать файл в окне и запишет его имя в переменную asdf.
Для большей информации посмотрите Справку VBA по слову Dialogs и ее раздел, называющийся Displaying built-in Word dialog boxes. Думаю, Вы найдете там немало интересного.
В Microsoft Excel тоже есть возможность вызова встроенных окон открытия и сохранения файлов. Так, окно открытия файла вызывается командой
Application.GetOpenFilename
а окно сохранения - командой
Application.GetSaveAsFilename
Их точный синтаксис посмотрите в Справке по этим командам. В отличие от Word, в Excel можно задавать также и заголовки окон, и даже надписи на кнопках.

12.
"как в MS Word VBA получить список доступных пользовательских макросов (в виде массива или коллекции строк)"
То, что Вы непосредственно имеете в виду - т.е. список макросов, отображающихся в одноименном окне "Макросы" - увы, средствами VBA получить нельзя, во всяком случае, мне такой способ неизвестен. Можно лишь получить список имен модулей, в которых код макросов содержится:
asd = NormalTemplate.VBProject.VBComponents.Count
ReDim a(asd) As String
p = ""
For nn = 1 To asd
a(nn) = NormalTemplate.VBProject.VBComponents(nn).Name
p = p + NormalTemplate.VBProject.VBComponents(nn).Name + Chr$(13)
Next nn
Selection.TypeText Text:=p
В результате в документ будет выведен список имен модулей шаблона Normal. Тот же список будет помещен в массив а(). В каждом модуле может содержаться как несколько макросов, могущих быть независимо исполненными, так и ни одного.

13.
"Высылаю документ. Мне нужно, чтобы при загрузке формы заполнялись ее поля содержимым текстовых рамок (на листе документа)."
В общем виде - будет так. Сначала следует узнать имя той рамки, из которой должен браться текст. Сделать это можно, например, командой MsgBox Selection.ShapeRange.Name, выделив ее в отдельную процедуру и запустив. Получится нечто вроде "Text Box 293". Следует запомнить это имя.
Затем в программу, в раздел Sub UserForm_Initialize() вписывается команда, которая из этой самой рамки текст вытаскивает. Если она не в колонтитуле, то выглядит как
TextBoxXX.Text=ActiveDocument.Shapes("Text Box 293").TextFrame.TextRange,
а если в колонтитуле - то
ActiveDocument.Sections(1).Footers(wdHeaderFooterPrimary).Shapes("Text Box 293").TextFrame.TextRange
или с номером соответствующего раздела - Sections(2) и т.д.
К примеру, если в Ваш шаблон, в раздел программного кода формы добавить такую процедуру:
Private Sub UserForm_Initialize()
TextBox9.Text = ActiveDocument.Sections(1).Footers(wdHeaderFooterPrimary).Shapes("Text Box 293").TextFrame.TextRange
End Sub
то при запуске формы она возьмет имя "******" из рамки в колонтитуле внизу листа на третьей странице документа (то, что после слова "разраб.") и поместит его в свою графу "Разработал". Соответственно команды с другими номерами Shapes("Text Box ...") будут помещать в эту графу текст из других рамок документа.

14.
"Мне нужно составлять много документов, которые состоят из однотипных частей. Эти части периодически изменяются и надо, чтобы изменение отражалось во всех документах. Можно это сделать в WORD? Как? Если нет, то что посоветуете?"
Да, можно. Однако конкретная реализация зависит от реальной задачи.
Если надо просто собрать документ из других документов так, чтобы при изменении в них он автоматически изменялся, то следует воспользоваться механизмом внедрения документов. Делается это в диалоговом окне "Вставка - Обьект - Создание из файла". Укажите с помощью кнопки "Обзор" путь к файлу, который Вы хотите вставить в документ и пометьте галочкой позицию "Связь с файлом", обязательно убрав галочку с пункта "В виде значка". В результате в Ваш документ будет полностью вставлен указанный файл. Изменять его из содержащего его документа будет нельзя (вернее, можно, но файл просто откроется для редактирования), зато при изменении в исходном файле содержимое результирующего документа автоматически изменится.
Иными словами, поместите Ваши "однотипные части" в отдельные документы и создавайте новые файлы, просто вставляя вышеописанным способом эти документы внутрь них.
Вы можете свободно менять содержимое "частей" - содержащий их файл изменится автоматически (вернее, по команде или при следующем его открытии).
Если Вам надо просто периодически делать документ, содержащий набор однотипных частей с меняющимся фрагментом (скажем, поздравления, в которых меняется только имя), то воспользуйтесь механизмом слияния ("Сервис - Слияние"). Работа с этим механизмом описана в Справочной системе Word. Смысл слияния - генерация набора однотипных документов с меняющимися вставками, располагающимися в т.н. "полях слияния", располагаемыми пользователем в основном документе слияния. Иными словами, на входе пользователь создает шаблон, наполняя его неизменяющимся содержанием и помечая места для вставок меняющихся текстов, прилагает к нему файл со списком меняющихся фрагментов и получает набор документов, содержащий каждый неизменный текст и одну из вставок из списка.

15.
"Меня интересует, как получить номера рядов и столбцов границ текущего выделения (объект Selection), т.е. ряд и столобец начала выделения (конец я могу узнать, прибавив Selection.Rows.Count)."
Есть такое хорошее свойство обьекта Selection - Selection.Information. Среди параметров этого свойства есть и те, что Вам требуются:
Selection.Information(wdStartOfRangeColumnNumber) - возвращает номер столбца начала выделения
Selection.Information(wdStartOfRangeRowNumber) - возвращает номер строки начала выделения
Selection.Information(wdEndOfRangeColumnNumber) - возвращает номер столбца конца выделения
Selection.Information(wdEndOfRangeRowNumber) - возвращает номер строки начала выделения
Они, естественно, работают лишь в таблице - вне таблицы возвращают "-1".
В Excel все значительно проще - то, что Вам надо, выдает команда
Selection.Address
Результат ее работы представляется в виде строчки типа "$B$4:$G$15". Такую строку можно разобрать командами обработки строки - Mid, Left, Right. Вид этой строчки определяется параметрами свойства Address: так, команда Selection.Address(RowAbsolute:=False, ColumnAbsolute:=False) выдаст строку "B4:G15".
Чтобы узнать адрес самой верхней левой выделенной ячейки, используйте команду ActiveCell.Address. Вышеуказанные параметры также влияют на вид результата: так, команда ActiveCell.Address (RowAbsolute:=False, ColumnAbsolute:=False) выдаст результат типа "B4".
Чтобы адрес содержал в себе номера как ряда, так и стобца, используйте такой формат команды:
ActiveCell.Address(ReferenceStyle:=xlR1C1)

16.
"Но хотелось бы написать программу, которая просаматривает уже отформатированный документ и по его образу и подобию форматирует другой текстовый документ с точностью до его слов. Но здесь хотелось бы знать какие команды было бы полезно использовать."
Это сделать довольно просто. Например, примерно так:
Sub belyakov()
ct = Documents(1).Paragraphs.Count
For y = 1 To ct
a = Documents(1).Paragraphs(y).Range.Words.Count
ReDim b(a) As Boolean
ReDim c(a) As Boolean
ReDim d(a) As Boolean
For n = 1 To a
If Documents(1).Paragraphs(y).Range.Words(n).Bold = True Then b(n) = True Else b(n) = False
If Documents(1).Paragraphs(y).Range.Words(n).Italic = True Then c(n) = True Else c(n) = False
If Documents(1).Paragraphs(y).Range.Words(n).Underline = True Then d(n) = True Else d(n) = False
Next n
For n = 1 To a
If b(n) = True Then Documents(2).Paragraphs(y).Range.Words(n).Bold = True
If c(n) = True Then Documents(2).Paragraphs(y).Range.Words(n).Italic = True
If d(n) = True Then Documents(2).Paragraphs(y).Range.Words(n).Underline = True
Next n
Next y
End Sub
Этот макрос делает точь-в-точь то, что Вы сказали. Документ-образец должен быть открыт первым (вместо "Documents(1) можно ставить Documents("Имя")), тот, что подлежит обработке - вторым.

17.
"Вкратце. Некая программа генерит текстовые файлы. Причем авторы ее сильно головой не думали и делали "абы как". В результате получается следующее. Многостраничный документ, в котором идут таблицы разной ширины. Причем ширина зачастую больше, чем может посимвольно пропечатать широкий принтер. Т.е. на обычный скажем Эпсон вывести уже не получается. потому что что не влезло или пропадет, или перейдет на другую строку - зависит от настроек принтера. Мало того, таблицы идут вперемешку - узкие и широкие, т.о. приходится печатать на бумаге А3 формата когда надо и когда не надо. Ну и хуже всего, конечно, то, что это таблицы, оформленные в виде текста. Т.е. применять к ним к-либо форматирование нельзя - только менять размер шрифта. Соответственно, приходится заниматься высокоинтеллектуальным трудом - бегло проглядывать каждый документ, менятть ориентацию и шрифт если надо, печатать. И так до посинения. интереса для - одну из таблиц приходится печатать 5 (!!!) шрифтом..."
Если я правильно Вас понял, то нижеследующий макрос может помочь Вам (комментарий относится к коду над ним).
Sub prog()
While Documents.Count > 0
'Перед началом работы откройте в Word все документы, которые нужно обработать.
sas = WordBasic.[FileNameInfo$](ActiveDocument.Name, 4)
sas1 = ActiveDocument.Path
'Получение имени и пути документа для сохранения
a = 0
For Each gh In ActiveDocument.Paragraphs
b = gh.Range.Characters.Count
If a < b Then a = b
Next gh
'Определение максимальной длины абзаца (т.е. строки в исходном документе) в символах
Select Case a
'В зависимости от определенной максимальной длины строки процедуре podobr, устанавливающей ориентацию страницы и размер шрифта, передаются параметры - ориентация (0 - книжная, 1 - портретная) и размер шрифта в пт). Вам, возможно, придется немного поподбирать длины строк, хотя я опытным путем определил их именно такими.
Case 1 To 50
podobr 0, 14
Case 51 To 56
podobr 0, 12
Case 57 To 82
podobr 1, 12
Case 83 To 100
podobr 1, 10
Case 101 To 125
podobr 1, 8
Case 126 To 165
podobr 1, 6
Case Else
dd = MsgBox("Не удается подобрать шрифт", vbCritical, "Сообщение")
'Если очень длинные строки - возьмите лист А3
Exit Sub
End Select
ActiveDocument.SaveAs FileName:=sas1 + "\" + sas, FileFormat:=wdFormatDocument
ActiveDocument.Close
'Сохранение документа в той же папке с тем же именем, но в формате Word. Можете эти строки заменить командой печати документа
Wend
'Конец цикла обработки всех открытых документов
End Sub
'
Sub podobr(o As Byte, sh As Integer)
'Подпрограмма установки ориентации страницы и размера шрифта
With ActiveDocument.PageSetup
If o = 0 Then .Orientation = wdOrientPortrait Else .Orientation = wdOrientLandscape
.TopMargin = CentimetersToPoints(1)
.BottomMargin = CentimetersToPoints(1)
.LeftMargin = CentimetersToPoints(1)
.RightMargin = CentimetersToPoints(1.8)
'Эти параметры - поля страницы - Вам, возможно, придется изменить для своего принтера. Тогда соответственно переопределите и размеры строк, указываемых при выборе размера шрифта и ориентации в основной программе
.Gutter = CentimetersToPoints(0)
.HeaderDistance = CentimetersToPoints(0)
.FooterDistance = CentimetersToPoints(0)
.PageWidth = CentimetersToPoints(29.7)
.PageHeight = CentimetersToPoints(21)
'Это тоже может потребовать изменения
End With
Selection.WholeStory
'Выделение всего документа
With Selection.Font
.Name = "Times New Roman"
.Size = sh
'Установка шрифта
End With
With Selection.ParagraphFormat
.LeftIndent = CentimetersToPoints(0)
.RightIndent = CentimetersToPoints(0)
.SpaceBefore = 0
.SpaceAfter = 0
.Alignment = wdAlignParagraphLeft
.WidowControl = True
.KeepWithNext = False
.KeepTogether = False
.PageBreakBefore = False
.NoLineNumber = False
.Hyphenation = True
.FirstLineIndent = CentimetersToPoints(0)
'Ну, и абзаца - тоже. Нам ведь не нужны красные строки...
End With
'Вроде все
End Sub
Поэкспериментируйте с данным кодом. Чтобы его использовать, надо открыть в нем все подлежащие обработке документы и запустить макрос. Все обработанные документы будут сохранены в тех же папках, что и исходные, под своими именами, но с расширением .doc и в формате Word.
"А как можно вставить в начало документа строчку с его названием, чтобы если чего криво напечатается, проще было бы найти?"
Командами
Selection.HomeKey Unit:=wdStory
Selection.TypeText Text:=ActiveDocument.Name + Chr$(13)

18.
"Как распечатать на листах формата А4 большой документ, что бы эти листы потом можно было склеить и получить боьшой плакат. Документы сделаны в Word или Exel. Может быть есть такой макрос или утилита, которые сами "делят" документ на отдельные листы и печатают. Помогите пожалуйста очень надо."
В Excel такая возможность встроена и так - для просмотра разбиения на листы А4 достаточно переключиться в режим разметки страницы (меню "Вид"). При достаточной ширине занимаемой текстом площади она будет распространяться на другие листы А4.
В Word подобной возможности нет, утилит - тоже (по всей видимости, все, кому такая возможность требуется, прибегают к помощи Excel'а). Рекомендую Вам переместить через буфер обмена текст из документов Word в файлы Excel и там уже распечатывать.

19.
"Здравствуйте. Вы не подскажите как в MS Word_XP сделать так, чтобы в верхнем колонтитуле при сохранении файла или его распечатке вставлялась информация о количестве слов в документе + дата/время сохранения."
Для этого Вам следует воспользоваться т.н. "полями". Перейдите в режим редактирования колонтитулов ("Вид" - "Колонтитулы") и, установив курсор на желаемое место в колонтитуле, вызовите диалоговое окно вставки полей ("Вставка" - "Поле"). Поле отображения информации о количестве слов в документе - раздел "О документе", поле "DocProperty", свойство "Words". Поле отображения даты/времени сохранения - раздел "О документе", поле "DocProperty", свойство "LastSavedTime" (во избежание проблем с обновление рекомендуется при вставке этого поля снять галочку с пункта "Сохранять формат при обновлении".
Для обновления полей в соответствии с текущим состоянием документа войдите в режим отображения колонтитулов, выделите одно поле или весь текст колонтитула и нажмите клавишу F9. Кроме того, Вы можете установить в диалоговом окне "Сервис" - "Параметры", на вкладке "Печать" отметку в пункте "Обновлять поля", и тогда поля будут обновляться при печати автоматически.
Вы можете написать такой макрос для более быстрого обновления полей в верхнем колонтитуле:
Sub obncol()
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
Selection.WholeStory
Selection.Fields.Update
ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
End sub
Назначьте ему кнопку на панели инструментов и обновляйте поля перед сохранением.
Если же Вы поместите в какой-нибудь из модулей Normal.dot такой макрос:
Sub FileSave()
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
Selection.WholeStory
Selection.Fields.Update
ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
ActiveDocument.Save
End Sub
то обновление полей в колонтитуле будет происходить автоматически и при сохранении документа. Назначать данному макросу специальную кнопку не нужно - он заменит собой команду сохранения документа.

20.
"В макросе я выделяю весь текст, копирую в буфер (в буфере он без содержимого колонтитула), и создаю пустой документ. А он же создается на основе шаблона нормал.дот :)... (т.е. с колонтитулом :( Я не знаю как создать макросом документ на основе другого шаблона (чистого)"
Создайте чистый шаблон без колонтитулов. Запишите путь к нему. А затем укажите этот путь в параметре Template команды Document.Add:
Document.Add Template="C:\Program Files\Office\Templates\Nocols.dot"
Вставьте такую строчку в макрос в качестве команды создания нового документа.

21.
"У меня возникла такая проблема: из всех файлов (*.doc) необходимо извлечь содержание (создано автоматически) Посоветуйте как можно добиться нужного результата. Может какая прога есть, или как её написать (знаю VB)"
Программ таких не знаю. Написать ее просто - достаточно в каждом документе выделить все элементы, входящие в коллекцию TablesOfContents, скопировать их в буфер обмена, а затем вставить как текст в новый документ.
Например, подобное делает следующая программа. Предполагается, что документы, из которых надо извлечь содержание, находятся в папке "C:\Desktop\test", имеют расширение ".doc", а готовый результат надо вставить в уже открытый документ.
With Application.FileSearch
'начинаем поиск файлов .doc в указанной папке
.NewSearch
.LookIn = "C:\Desktop\test"
.FileName = "*.doc"
.SearchSubFolders = False
.MatchTextExactly = True
.FileType = msoFileTypeAllFiles
'имена всех найденных файлов записываются в массив .FoundFiles (см. справку)
.Execute
For qqq = 1 To .FoundFiles.Count
'теперь переберем все элементы этого массива
Documents.Open FileName:=.FoundFiles(qqq)
'каждый откроем
For Each a In ActiveDocument.TablesOfContents
a.Range.Select
'выделим в нем содержание (см. справку по слову TablesOfContents)
a.Range.Copy
'скопируем его в буфер
Next a
ActiveDocument.Close
'закроем документ, при этом активируется предыдущий - тот, в который надо вставить содержание
Selection.PasteSpecial Link:=False, DataType:=wdPasteText, Placement:=wdInLine, DisplayAsIcon:=False
'и вставим содержание "Специальной вставкой"
Next qqq
End With
'и так со всеми документами
Скопируйте этот код в Редактор VBA и модифицируйте его под свои нужды.

22.
"Не подскажите, существует ли такой макрос в Excel, который подчеркивает всю строку и столбец цветными линиями через правый - нижний угол выделенной ячейки? Где-то я такое очень давно встречал, но не в Excel."
Макрос может быть таким:
Sub macro()
a = ActiveCell.Row
b = ActiveCell.Column
с = ActiveCell.Address
Columns(b).Select
With Selection.Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlThick
.ColorIndex = 3
End With
Selection.Borders(xlInsideHorizontal).LineStyle = xlNone
Rows(a).Select
With Selection.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlThick
.ColorIndex = 3
End With
Selection.Borders(xlEdgeRight).LineStyle = xlNone
Range(с).Select
End Sub
Скопируйте этот код в раздел макросов листа или книги Редактора VBA и запускайте всякий раз, когда Вам надо провести указанную Вами операцию над выделенной ячейкой. Параметры .ColorIndex задают цвет, параметр .Weight - толщину линии (чтобы была тонкой, укажите в нем .Thin).
"Спасибо за помощь. Вот еслиб еще это перекрестие "следило" за активной ячейкой после запуска макроса?"
Для этого надо добавить данный макрос в процедуру обработки события "SelectionChange", немного его переработав:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
a = Target.Row
b = Target.Column
с = Target.Address
Cells.Borders(xlDiagonalDown).LineStyle = xlNone
Cells.Borders(xlDiagonalUp).LineStyle = xlNone
Cells.Borders(xlEdgeLeft).LineStyle = xlNone
Cells.Borders(xlEdgeTop).LineStyle = xlNone
Cells.Borders(xlEdgeBottom).LineStyle = xlNone
Cells.Borders(xlEdgeRight).LineStyle = xlNone
Cells.Borders(xlInsideVertical).LineStyle = xlNone
Cells.Borders(xlInsideHorizontal).LineStyle = xlNone
With Columns(b).Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlThick
.ColorIndex = 3
End With
Columns(b).Borders(xlInsideHorizontal).LineStyle = xlNone
With Rows(a).Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlThick
.ColorIndex = 3
End With
Rows(a).Borders(xlEdgeRight).LineStyle = xlNone
End Sub
Для использования этого макроса надо открыть Редактор VBA, выбрать для любого листа нужной книги пункт View Code (обратите внимание - именно листа, а не всей книги и тем более не помещать макрос в отдельный модуль) и поместить его туда. "Перекрестие" будет перемещаться за активной ячейкой в этом листе.
Для того, чтобы при перемещении выделения старые линии уничтожались, в макрос добавлен набор команд, очищающих лист от всех линий. Если это не нужно - удалите из макроса блок строк, начинающихся с Cells.Borders.
Макрос, бесспорно, можно дорабатывать - сделать так, чтобы удалялись только им же отрисованные линии, сделать функцию включения/выключения режима выделения и т.д. Но это - уже более сложные задачи.

23.
"Можно ли документу назначить принтер, не используемый по умолчанию? т.е. чтобы при открытии документа и отправке его на печать печать шла на определенный сетевой принтер?"
Да, конечно. Для этого служит команда ActivePrinter:
ActivePrinter = "\\NAME\Printer"
Имя принтера нужно указывать вместе с путем и с точностью до символа. В результате выполнения этой команды принтер по умолчанию будет переназначен.
Для реализации Вашего желания добавьте в документ макросы AutoOpen и AutoClose, в первом из которых назначайте активным сетевой принтер, а во втором - используемый по умолчанию.
"Можно ли сделать автокопирование из одной ячейки табилцы в другую, при том что это текст?"
Да.
Первый способ: вставить в документ "Таблицу Microsoft Excel", и все оформление перенести в нее. В ту ячейку, где должен отображаться текст, вставить формулу "=<адрес ячейки, откуда брать текст>". В этом случае обновление происходит автоматически после завершения изменения текста в исходной ячейке.
Второй способ: пометить исходный текст закладкой, а на второе место вставить формулу, отображающую эту закладку. Например, если имя закладки - name, то на второе место нужно вставить формулу ("Таблица" - "Формула"), из диалогового окна вставки формулы удалить знак "=" и выбрать из списка "Вставить закладку" соответствующее имя закладки. Можно также вставить поле ("Вставка" - "Поле") и в качестве кода поля указать имя закладки. В аттачменте - Ваш документ, с которым такое проделано.
Недостаток способа - требуется выполнять команду обновления полей каждый раз после изменения текста. На VBA это выполняется командой
ActiveDocument.Fields.Update
Создайте макрос с этой командой и вызывайте его перед печатью.
Кстати, если надо сгенерировать множество однотипных документов с изменениями только в одной-двух строчках (скажем, напечатать визитки всем из какого-нибудь их списка), то следует использовать "Мастер Слияния" - (WordXP) "Сервис" - "Письма и рассылки" - "Мастер слияния", а не заниматься ручным вводом имен в каждую визитку.
"Еще сходный вопрос: можно ли как-нибудь сделать печать нумерованных документов, например - билетов? Я это делал по такой же методе - сначала печатаю сами билеты (документ 1-страничный, допустим 10 билетов на странице, 2 колонки по 5), потом делаю таблицу, столбец один, строк по числу билетов, делаю автонумерацию от 1 до N, делаю оформление в 2 колонки, подгоняю расположение номера на странице, получается N/10 листов, и печатаю на заранее подготовленных бланках без номеров."
Да, конечно, можно. Сделайте текстовый файл с числами от 1 до N на отдельных строчках (просто создайте автоматическую нумерацию в файле Word с нужным количеством строк, а потом сохраните этот файл в формате txt), а затем воспользуйтесь "Мастером слияния". Разберитесь с его действием сами - обьяснять долго, а понять можно быстро; в результате же Вы получите набор пронумерованных билетов, которые останется только распечатать.

24.
"Во-первых не получается макрос перевода нормальных ссылок в список литературы. Кое-как сделал путем записи макроса "перевести ссылки в концевые, скопировать их в буфер, перевести ссылки в обычные, курсор в конец док-та, вставить из буфера, применить форматирование, сортировать по АВС". Потом ручками удаляю номера сносок и повторяющиеся сноски. Понимаю, что криво, но не силен, а работать приходится много. Можете ли Вы помочь?"
По всей видимости, Ваш путь наиболее правилен. Разве что удаление номеров сносок и повторяющихся сносок можно тоже автоматизировать макросом. Кроме того, переводить ссылки в концевые необязательно - достаточно перейти в режим просмотра "Обычный" и вызвать команду "Вид" - "Сноски", после чего скопировать все содержимое открывшегося окна просмотра сносок в буфер обмена и вставить в конец документа. Заодно все номера сносок превратятся в "1", так что автоматически удалить их будет куда как проще. Все это можно записать в макрос даже без работы с Редактором VBA.
К сожалению, насколько я знаю, в Word нет встроенной функции, выполняющей то, что Вы хотели.
"Второй вопрос проще - можно ли начать нумерацию страниц не с первой или второй, а например с 3 страницы документа, причем, чтоб она была, например 2. Встретилась как-то необходимость вставить после титульного листа еще один, но не нумеровть его, следовательно 3-й лист должен быть под номером 2. Я не смог:(("
Да, конечно, можно.
Алгоритм действий таков:
1. Убрать всю нумерацию, если она уже была установлена.
2. Поставить курсор в конец последнего листа, который должен быть без номера.
3. Выполнить команду "Вставка" - "Разрыв" - "Новый раздел" - "Со следующей страницы".
4. Поставить курсор на страницу, следующую за вставленным разрывом.
5. Переключиться в режим редактирования колонтитулов: "Вид" - "Колонтитулы".
6. Поставить курсор в то место верхнего или нижнего колонтитула, на котором должен стоять номер страницы.
7. Посмотреть на панель инструментов "Колонтитулы". Обратить внимание на кнопку "Как в предыдущем разделе". Эта кнопка включает или отключает связь колонтитулов в разных разделах.
8. Если режим "Как в предыдущем разделе" включен (как на рисунке) - то отключить его.
9. Теперь можно вставлять номера страниц - следует выполнить команду "Вставка" - "Номера страниц".
10. Чтобы начать нумерацию не с номера 1, в окне вставки номеров страниц следует нажать кнопку "Формат", и в открывшемся диалоговом окне в соответствующем поле указать число, с которого следует начинать нумерацию.
Иными словами - ставите курсор в конец 2 страницы, вставляете разрыв раздела, открываете колонтитул, отжимаете кнопку связи колонтитулов, вставляете нумерацию, задаете число начала нумерации.

25.
"Существует некий файл Name.xml.doc эквивалент текстового файла Name.xml. Требуется написать программу которая сохраняет этот файл как txt файл с тем же самым именем но с удаленным doc расширением."
Способов сделать это много. Например, если данный файл уже открыт в Word, то такое сохранение выполняет команда
ActiveDocument.SaveAs FileName:="Name.xml", FileFormat:=wdFormatText
Если же документ открывать нецелесообразно, то можно воспользоваться таким кодом, просто переименовывающий документ:
OldName = "C:\Desktop\Name.xml.doc"
NewName = "C:\Desktop\Name.xml"
Name OldName As NewName
Вместо указанного в коде пути следует подставить свои значения.
Если Вам просто нужно получить имя без последнего расширения, то для этого следует использовать команду
Left("имя файла с расширением .doc", Len("имя файла с расширением .doc") - 4)
Имя файла целесообразно записать в переменную.
Так, например, в результате выполнения кода
a = "Name.xml.doc"
b = Left(a, Len(a) - 4)
в переменной b будет записано значение "Name.xml".
А в результате выполнения кода
ActiveDocument.SaveAs FileName:=Left(ActiveDocument.Name, Len(ActiveDocument.Name) - 4), FileFormat:=wdFormatText
открытый в Word документ будет сохранен в формате "только текст" без последнего расширения.

26.
"Извините, oпять пытaюсь рaскусить oчередную зaдaчу. В прилaгaемoм фaйле (content of help file "Winzip" ) нужнo oтметить текст пoсле "=" в кaждoй стрoке стилем "tw4winInternal", a oстaльнoй текст-стилем "Normal" (или .font.reset) Помогите пожалуйста, если знаете как.
Заранее благодарен."
Следующий код, полученный в результате небольших исправлений записанного макроса, выполняет Вашу задачу:
'Выделить все:
Selection.WholeStory
'Назначить стиль "Normal" (важно правильно написать название стиля - иначе команда не сработает)
Selection.Style = ActiveDocument.Styles("Normal")
'Снять выделение:
Selection.MoveLeft Unit:=wdCharacter, Count:=1
'Установить параметры поиска - ищем знак =:
Selection.Find.ClearFormatting
With Selection.Find
.Text = "="
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
'Теперь ищем все знаки = и, найдя каждый из них...
While Selection.Find.Execute = True
'выделяем текст от знака = до конца строки без символа конца абзаца
Selection.MoveRight Unit:=wdCharacter, Count:=1
Selection.EndKey Unit:=wdLine, Extend:=wdExtend
Selection.MoveLeft Unit:=wdCharacter, Count:=1, Extend:=wdExtend
'и применяем к нему стиль.
Selection.Style = ActiveDocument.Styles("tw4winInternal")
Selection.Collapse
Wend
"Текст отмеченный стилем "tw4winExternal" пропадает, хотя мне казалось что на другой машине я его видел???"
Ну естественно - текст же в этом стиле помечается как "скрытый"! Разве не в этом и было предназначение макроса?
Чтобы отобразить скрытый текст, следует включить отображение непечатаемых символов.
"Как сделать так чтобы знак "=" тоже отмечался "tw4winExternal"?"
Изменения выделены красным:
While Selection.Find.Execute = True
Selection.MoveLeft Unit:=wdCharacter, Count:=1
Selection.EndKey Unit:=wdLine, Extend:=wdExtend
Selection.MoveLeft Unit:=wdCharacter, Count:=1, Extend:=wdExtend
Selection.Style = ActiveDocument.Styles("tw4winInternal")
Selection.Collapse Direction:=wdCollapseEnd
Wend

27.
"Можно ли в макросе 001.bas прописать ИМПОРТИРОВАНИЕ другого макроса. Ну, например 002.bas (который находится, например, на C:/ ). Если "да", то как это сделать?"
Да, разумеется. Для импортирования файла с макросом в Normal.dot необходимо использовать команду
NormalTemplate.VBProject.VBComponents.Import ("путь к файлу макроса")
Чтобы импортировать макрос в открытый документ, следует использовать команду
Documents("имя документа с расширением").VBProject.VBComponents.Import ("C:\путь кфайлу макроса")

28.
"Есть вопрос - как в Worde 97 узнать номер страницы (абсолютный), на которой курсор мигает, или каким нибудь другим образом сделать подобное..."
Существуют функции Selection.Information(wdActiveEndPageNumber), которая возвращает номер страницы по счету, на которой располагается конец выделения, и функция Selection.Information(wdActiveEndAdjustedPageNumber), которая возвращает присвоенный номер страницы, на которой располагается выделенный фрагмент.
Вторую функцию следует использовать тогда, когда необходимо получить тот номер страницы, который указан на ней непосредственно (т.е. с учетом ручных установок нумерации), а первую - если номер необходим абсолютный (т.е. то, что Вам требуется). Описание обеих команд можно получить в Справке VBA по слову Information.

29.
"как вычислить к-во страниц в документе Excel с помощью VBA???"
Например, таким кодом:
a = (ActiveSheet.VPageBreaks.Count + 1) * (ActiveSheet.HPageBreaks.Count + 1)
В результате в переменную а будет записано количество страниц, на которых лист будет распечатан.

30.
"Часто, после открытия документа в Word-е оказывается что изменились привычные сочетания клавиш - Ctrl-C - Сtrl-Ins и тому подобное... Можно ли, и каким образом, переключится в привычное состояние? В чем причина подобных изменений?"
По умолчанию Word настроен так, что в том случае, если при запуске программы раскладка клавиатуры была русская, то используются комбинации клавиш Ctrl+Ins, Shift+Ins, F12 и т.д., а если была английская - то Ctrl+C, Ctrl+V и т.д.
Использовать какую-либо одну комбинацию клавиш можно, просто настроив их в шаблоне Normal.dot: "Сервис" - "Настройка" - "Клавиатура", там для каждой команды можно ввести желаемое сочетание клавиш для вызова.
Настройте комбинации клавиш для всех частоиспользуемых Вами команд.

31.
"Нужно условное форматирование яцейки, где условий более 3-х. И результаты форматирования разные! Неужели это невозможно? М.б. можно свои функции завести?"
В отдельной ячейке надо добавить логическую функцию, значение которой будет служить источником для условного форматирования нужной ячейки.
Пример. Допустим, нам надо, чтобы ячейка B1 должна быть красной, если А1>0 и A2>1 и A3>2 и A4>3 и А5>2. Делаем так: в B2 вставляем формулу, которая возвращает True, если все это условие выполняется (такую формулу нетрудно написать самому - обратите внимание на раздел "Логические" в списке встроенных формул), и False, если это не так. Понятно, что в формуле может быть сколько угодно аргументов и сколько угодно условий.
А затем делаем условное форматирование на B1 в зависимости от значения этой самой формулы в ячейке B2. Например, "если B2 - True, тогда B1 - красная".

32.
Запустил макрос на выполнение. Он автоматически сворачивается и выполняет свою работу, а именно - формирует таблицу. Как с помощью макроса отобразить на свёрнутом окне проценты от выполненной макросом работы на данный период времени?"
Смотря где Вы желаете их отображать. Если в статусной строке - то для этого служит свойство StatusBar:
StatusBar = "код, выводящий процент"
Если же Вы желаете отобразить на экране бегущую полоску или счетчик, то можете во время работы макроса вывести на экран окно формы, а код отображения на этой форме счетчика поместить в обработчик события UserForm_Activate(). Этот код будет выполнен сразу после отображения формы, и в нем могут быть команды, управляющие внешним видом формы.
Пример кода Вы можете взять в программе "ВерсткаТекстаКнижкой" - http://orlovs.pp.ru/soft.php. Он как раз отображает на экране процент выполненной работы путем использования формы и события UserForm_Activate().

33.
"как определить путь к открытому dot-файлу? (имею ввиде полный путь к файлу на диске.)"
Если к открытому в Word - то ActiveDocument.Path - путь без имени или ActiveDocument.FullName - путь с именем.
Если к загруженному глобально - то AddIns("Имя шаблона.dot").Path.

34.
"Как, если это возможно, создавать TextBox-ы уже с Visible=false?"
ActiveDocument.Shapes.AddTextbox(msoTextOrientationXXX, left, top, height, width).Visible = msoFalse
Чтобы сделать видимыми, примените, к примеру, команду
For Each ddd In ActiveDocument.Shapes
ddd.Visible = msoTrue
ddd.Line.Visible = msoTrue
Next ddd
Application.ScreenRefresh

35.
"Скажите, а Вы не в курсе, где можно найти макрос для Word, который бы прописывал в конец документа полный путь к файлу и его имя, а затем закрывал файл с сохранением? Или как это сделать?"
Это действие выполняет следующий макрос:
Sub cldoc()
Selection.EndKey Unit:=wdStory
Selection.TypeParagraph
Selection.TypeText Text:=ActiveDocument.FullName
ActiveDocument.Save
ActiveDocument.Close
End Sub
Поместите его в Normal.dot через Редактор VBA, а затем назначьте комбинацию клавиш или кнопку на панели инструментов.

36.
"Мне надо из экселя открыть документ ворд, и в нужных местах повпечатывать текст. Для этого я использую... а здесь я хочу переместить курсор но эксель на эту строку ругается. ... В чем проблемма?"
Дело в том, что управление одним приложением из другого все же имеет некоторые отличия от непосредственной работы с этим приложением.
Можно сказать, что открываемый с помощью автоматизации документ открывается как "статичный" - в нем можно менять слова, заполнять клетки таблиц, в него можно записывать текст, но в этом документе вообще нет понятия "курсор" и, соответственно, команды его движения неприменимы.
Менять слова и предложения может программа наподобие следующей:
Sub test()
Dim es As Object
Set es = GetObject("c:\example.doc")
With es.Application
.Visible = True
.ActiveDocument.Sentences(25) = "Новое предложение"
End With
End Sub
которая заменяет 25-е предложение документа на "Новое предложение".
К таблицам, их ячейкам, рисункам тоже можно обращаться напрямую, указывая в командах их порядковые номера в документе.
Вставить текст в определенное место документа тоже возможно, однако для этого необходимо применить несколько хитрый прием:
Sub test()
Dim es As Object
Set es = GetObject("c:\example.doc")
With es.Application
.Visible = True
.ActiveDocument.Characters(25).Select
.Selection.Collapse
.Selection.TypeText Text:="1"
End With
End Sub
Эта программа выделит 25-й символ документа, после чего свернет выделение к началу, но точка ввода останется на 25-й позиции в документе. Следующая команда введет текст на данную позицию.
Иными словами, при использовании автоматизации (то есть управления программой Microsoft Office из VBA-программы в другом приложении пакета) тот документ, к которому получается доступ, представляется программе не как собственно документ (в котором можно было бы работать курсором), а как набор пронумерованных символов, слов, предложений, таблиц, рисунков. Эти символы, слова и т.д. можно выделять, заменять, вводить новые, используя соответствующие команды VBA.

37.
"Есть некий текст. В нем все русские буквы нужно заменить на латинские, но не как в транслите, а по-особенному алгоритму. Каким макросом это сделать? Сведения о соответствии русских и латинских букв прилагаю.."
Вашу задачу куда как лучше решает такой макрос:
Sub macr()
a = "аАбБвВгГдДеЕжЖзЗиИйЙкКлЛмМнНоОпПрРсСтТуУфФхХцЦчЧшШщЩь"
b = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZb"
c = Len(a)
For d = 1 To с
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = Mid(a, d, 1)
.Replacement.Text = Mid(b, d, 1)
.Forward = True
.Wrap = wdFindContinue
.MatchCase = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
Next d
End Sub
который работает в Word97.

38.
"Дело, собственно, вот в чем. В Microsoft Word есть обьекты (музыкальные файлы,Flash-ролики,рисунки,итд.), которые можно вставлять в документ и проигрывать ( Меню Вставка &#8594; Обьекты+) Я хочу сделать так,что при нажатии кнопки (CommmandButton, с нею как раз то и проблем нет) вставленные в документ музыкальные файлы проигрывались.С реализацией алгоритма проблем нет, проблема в другом: я нигде - ни в справочной системе Редактора VBA, ни в Интернете - не могу найти информацию по методам и свойствам этих обьектов, чтобы реализовать данную опцию на программном уровне."
А для решения Вашей задачи это не надо. Достаточно VBA-метода .DoVerb.
Например, Вы вставили в документ MP3-файл. Он, разумеется, вставился не так просто, а как значок, к примеру, в виде "объекта в текстовом слое" - InlineShape (или просто Shape, если не в текстовый слой). В итоге он получил свой индекс в коллекции InlineShapes или Shapes соответственно. Обратившись к нему по этому индексу методом .DoVerb, вы сможете отдавать приказания этому объекту.
Так, если индекс объекта в коллекции InlineShapes - 1, то команда
ActiveDocument.InlineShapes(1).OLEFormat.DoVerb
сделает то же самое, что и двойной клик на объекте: запустит его.
У метода DoVerb есть параметры - это различные действия с объектом. Вы можете прочитать о них в Справке VBA по ключевому слову DoVerb.
Более сложные действия со встроенным объектом, действительно, нужно осуществлять с помощью специальных команд, но в таком случае к программе, обрабатывающей эти объекты, ее разработчик должен приложить список таких команд. Без такого списка находить имена команд можно только методом угадывания.
"Хотелось бы поинтересоваться еще об одном: я где-то читал,что можно сделать так,чтобы макросы автоматически запускались с открытием документа."
Можно. Создайте в документе (в любом модуле) макрос с именем AutoOpen. Он и выполнится при открытии этого документа, разумеется, если у пользователя не отключена обработка макросов. Например, такое используется в инсталляторах программ (см. http://orlovs.pp.ru/soft.php).
Кстати, чтобы такие макросы не выполнялись при открытии документа, в момент открытия следует удерживать клавишу Shift.

*   *   *

В раздел "Компьютерные технологии"
На главную страницу