Показать полную графическую версию : Замена шифра в тексте и печать большого количества документов
AKBAMAPUH
12-09-2012, 22:11
Имеется документ MS Word, который состоит из двух страниц. На первой странице документа в четырех местах имеется шифр вида "x" и этот шифр необходимо менять в арифметической последовательности "x+1" (то есть сначала в четырёх местах написан шифр "x", потом шифр меняется и во всех четырёх местах напсиан шифр "x+1" и так далее, до определённого значения), а остальной текст оставлять без изменений и при этом распечатывать каждый раз при изменении значения в автоматическом режиме, используя двустороннюю печать.
Используя возможности VB я добился следующего:
1 - при открытии документа у меня появляется форма, в которую я ввожу начальное значение шифра вида "x", потом ввожу общее число необходимых мне подстановок "y"
2 - кнопка "подстановка" меняет шифр вида "x" на введённое значение в создаваемом документе в необходимых мне четырёх местах (это я сделал при помощи закладок). На текущий момент времени я могу создавать только один документ с введённым форму значением.
3 - кнопка "отмена" закрывает форму, потом документ и затем закрывает Word
Вот как это выглядит на текущий момент времени
Private Sub CommandButton1_Click()
If CheckBox1.Value = False Then
MsgBox "Ошибка!" & " " & "Необходимо принять условие." 'выводим сообщение
Else
Dim oDoc As Document
Set oDoc = Application.Documents.Add("C:\Template.dotm")
oDoc.Bookmarks("bN_1").Range.Text = txtBlank.Value
oDoc.Bookmarks("bN_2").Range.Text = txtBlank.Value
oDoc.Bookmarks("bN_3").Range.Text = txtBlank.Value
UserForm1.Hide
oDoc.Activate
End If
End Sub
Private Sub CommandButton2_Click()
'Выход из формы и закрытие окна документа при нажатии кнопки "Отменить"
On Error GoTo ErrLabel
Unload Me 'Закрываем форму
ActiveDocument.Close 'Закрываем текущий документ
ErrLabel:
Application.Quit 'закрываем Word
End Sub
Private Sub txtBlank_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'действия с полем номер бланка
With Me.txtBlank
If Not IsNumeric(.Text) Or Len(.Text) <> 6 Then 'если в поле "Бланк" данные не цифры и меньше или больше 6, то
MsgBox "Ошибка!" & " " & "Введите 6 цифр бланка." 'выводим сообщение
Cancel = True 'возвращаемся к полю
.Text = "" 'очищаем поле
.SetFocus
End If
End With
End Sub
Private Sub txtKolvo_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'действия с полем общее количество бланков
With Me.txtKolvo
If Not IsNumeric(.Text) Or Len(.Text) <> 2 Then 'если в поле "общее количество бланков" данные не цифры и общее число цифр меньше или больше 2, то
MsgBox "Ошибка!" & " " & "Вводить только число, состоящее из 2 цифр." 'выводим сообщение
Cancel = True 'возвращаемся к полю
.Text = "" 'очищаем поле
.SetFocus
End If
End With
End Sub
вот нашёл код, он мне в принципе должен помочь, но я пока не могу его изменить под себя...
здесь приводится пример как на странице документа выставляется каждый раз новое число с одного до другого и каждый раз при этом документ распечатывается.
я надеюсь правильно понял пример =)
Sub Печать_кучи_документов_с_номерами()
' В документе там где должен быть номер должна стоять 239366 '
For Номер_документа = 239366+1 To 239366+100
With Selection.Find
.Text = Trim(Str(Номер_документа - 1))
.Replacement.Text = Trim(Str(Номер_документа))
.Forward = True
.Wrap = wdFindContinue
End With
Selection.Find.Execute Replace:=wdReplaceAll
Application.PrintOut Range:=wdPrintAllDocument, Item:= _
wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _
ManualDuplexPrint:=False, Collate:=True, Background:=True, PrintToFile:= _
False, PrintZoomColumn:=0, PrintZoomRow:=0, PrintZoomPaperWidth:=0, _
PrintZoomPaperHeight:=0
Next
End Sub
и ещё нашел вот такую статью (http://support.microsoft.com/?kbid=230743)
она меня безумно напугала из-за огромного кода на казалось бы простую операцию - установка дуплекса на печать документа
вообщем, как видите, пока что в голове бардак... Требуется помощь для наведения порядка в голове и мыслях.
IMHO, вы слишком усложняете. По сути, вам нужно выполнить цикл c глобальной заменой (как в первом примере) или перебором закладок с последующей печатью документа. Двухстороннюю печать на время выполнения кода проще задать в свойствах принтера по умолчанию, чтобы не связываться с WinAPI.
AKBAMAPUH
29-09-2012, 20:14
Dr.DG,
вот что мне удалось сделать на текущий момент времени:
Private Sub CommandButton1_Click()
Dim lNumber As Long
Dim i As Long
'Помещаем в переменную lNumber, с какого номера
'должна начинаться нумерация бланков.
lNumber = Me.TextBox1.Value
'проверяем на согласие с условием
If CheckBox1.Value = False Then
'выводим сообщение
MsgBox "Ошибка!" & " " & "Необходимо принять условие."
Else
'Делаем столько витков цикла, сколько бланков необходимо вывести на печать.
For i = 1 To Me.TextBox2.Value Step 1
Dim oDoc As Document
Set oDoc = Application.Documents.Add("C:\Primer\BLANK.docm")
'Помещаем в закладку "bN_1" данные из переменной lNumber.
oDoc.Bookmarks("bN_1").Range.Text = lNumber + (i - 1)
'Помещаем в закладку "bN_2" данные из переменной lNumber.
oDoc.Bookmarks("bN_2").Range.Text = lNumber + (i - 1)
'Помещаем в закладку "bN_3" данные из переменной lNumber.
oDoc.Bookmarks("bN_3").Range.Text = lNumber + (i - 1)
'Помещаем в закладку "bN_4" данные из переменной lNumber.
oDoc.Bookmarks("bN_4").Range.Text = lNumber + (i - 1)
'Распечатываем.
Application.PrintOut Range:=wdPrintAllDocument, Item:= _
wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _
ManualDuplexPrint:=True, Collate:=True, Background:=True, PrintToFile:= _
False, PrintZoomColumn:=0, PrintZoomRow:=0, PrintZoomPaperWidth:=0, _
PrintZoomPaperHeight:=0
'Скрываем пользовательскую форму
UserForm1.Hide
Next i
End If
End Sub
Здесь представлен работающий код, теперь уже с пользовательской формой (в которой TextBox1 и TextBox2 для ввода значений, CheckBox1 для принятия условия, а также кнопка CommandButton1, которая является основной).
По-прежнему есть некоторые моменты, которые хотелось бы улучшить:
1 - в документе "BLANK.docm", над которым и проводятся все действия, имеется 4 закладки на 4 одинаковых числа, которые начинаются с цифры "ноль". Например, 012222. Так вот сейчас я вынужден был перед каждой закладкой поместить цифру "ноль",а в поле TextBox1 пользовательской формы UserForm1 вбивать значение без цифры "ноль", например 12222.
Можно ли сделать так, чтобы в поле TextBox1 я вносил значение например 012222, в поле TextBox2 я вносил значение например 2 и при этом происходила правильная отработка "lNumber + (i - 1)" и на печать выводились документы с изменёнными номерами - 012222 в первом документе и 012223 во втором документе?
2 - во время выполнения кода открываются новые вкладки с документами, с изменёнными номерами. Как избавиться от этого, чтобы ничего не появлялось, а просто в очередь печати все документы складывались сразу и всё?
3 - необходима двусторонняя печать документа "BLANK.docm". Принтер обладает необходимой функцией.
AKBAMAPUH
29-09-2012, 20:48
по пункту 2 родилась вот какая идея
'закрываем активный документ без сохранения изменений, поскольку после вставки
'текста произошла замена закладки
ActiveDocument.Close SaveChanges:=wdDoNotSaveChanges
правильно сделал или есть более правильный вариант решения вопроса?
AKBAMAPUH
29-09-2012, 22:31
и ещё появились следующие вопросы (сохранена сквозная нумерация проблем):
4 - текст, вводимый в TextBox1, должен проверяться на следующие условия - это должно быть число, число должно состоять из 5 цифр, и не должно начинаться на ноль.
5 - текст, вводимый в TextBox2, должен проверяться на следующие условия - это должно быть число равное "1", "2" или "50".
1 - непонятно.
2 - новые вкладки (новые документы) создаются из-за этой строчки: Set oDoc = Application.Documents.Add("C:\Primer\BLANK.docm") Нужно так Set oDoc = ActiveDocument, но, так как вы работаете только с активным документом, IMHO, переменная oDoc вообще не нужна, обращайтесь напрямую к ActiveDocument.
3 - повторяю, задаёте двухстороннюю печать в свойствах принтера в Панели управления. ManualDuplexPrint:=True - это ручной дуплекс средствами Word.
4 - Проверка на число If IsNumeric(TextBox1.Value) Then
Else
End If Проверка на количество цифр If Len(TextBox1.Text) = 5 Then
Else
End If Проверка на 0 в первой цифре If Left(TextBox1.Text, 1) = "0" Then
Else
End If 5 - If TextBox2.Value = 1 _
Or TextBox2.Value = 2 _
Or TextBox2.Value = 50 _
Then
Else
End If
AKBAMAPUH
01-10-2012, 19:08
спасибо огромное за подсказки, сейчас всё переварю, отрихтую и проверю =)
AKBAMAPUH
01-10-2012, 19:28
Итак, сходу образовалась вот какая проблема:
решил использовать ActiveDocument, убрав переменную oDoc, то есть строки стали вот какимим
'Помещаем в закладку "bN_1" данные из переменной lNumber.
ActiveDocument.Bookmarks("bN_1").Range.Text = lNumber + (i - 1)
'Помещаем в закладку "bN_2" данные из переменной lNumber.
ActiveDocument.Bookmarks("bN_2").Range.Text = lNumber + (i - 1)
'Помещаем в закладку "bN_3" данные из переменной lNumber.
ActiveDocument.Bookmarks("bN_3").Range.Text = lNumber + (i - 1)
'Помещаем в закладку "bN_4" данные из переменной lNumber.
ActiveDocument.Bookmarks("bN_4").Range.Text = lNumber + (i - 1)
при таком раскладе выяснилось, что я похоже неправильно использую закладки (Bookmarks), то есть у меня происходит не подстановка значения на место закладки, а происходит полная замена закладки на указанное значение. И получается, что при втором витке в документе уже нет закладок, так как на их месте теперь просто указанные значения, соответсвенно цикл заканчивается на первом витке.
как правильно использовать подстановку на место закладки?
AKBAMAPUH
01-10-2012, 20:02
и еще вопрос у меня напрашивается например по пункту 5:
я не понимаю что мне писать в коде после слова Then
If TextBox2.Value = 1 _
Or TextBox2.Value = 2 _
Or TextBox2.Value = 50 _
Then
Else
End If
после слова Else я напишу чтобы появлялось MsgBox "Ошибка!" & " " & "Введите значение равное 1, 2 или 50"
а вот что после слова Then? что-то я не догоняю... мне бы наоборот сделать, чтобы если НЕ РАВНО, то сообщение, вот как-то так...
если пишу If Not , то проверяется только первое значение на 1, а дальше проверка не идёт...
If Not (TextBox2.Value = 1 Or TextBox2.Value = 2 Or TextBox2.Value = 50) Then
…
Else
…
End If
Оно же:
If TextBox2.Value <> 1 Or TextBox2.Value <> 2 Or TextBox2.Value <> 50 Then
…
Else
…
End If
происходит полная замена закладки на указанное значение. И получается, что при втором витке в документе уже нет закладок» Как вариант, перед заменой текста закладок сохранять в переменных/массивах начала и концы (Start и End) свойств Range закладок и потом создавать новые объекты Range и закладки на их основе в сохранённых местах.
AKBAMAPUH
01-10-2012, 22:26
Iska,
спасибо огромное за подсказку со скобками!
фантастика, как просто с одной стороны, но мне и в голову не пришло, что можно использовать скобку в таком случае.
P.S. вы даже не представляете, как много я уже узнал за последний месяц, решая эту задачу =)
Dr.DG,
да, я примерно понимаю о чём вы говорите... я находил на просторах инета что-то подобное, но не смог сделать, поскольку там явно были ошибки, которые мне не удалось решить.
сейчас найду ещё раз и буду внимательно изучать в этом направлении. Спасибо огромное!
Dr.DG,
кстати, по поводу нулей в начале шифра, вот что мне удалось найти
"0"&Cstr(lNumber + (i - 1))
вот как просто добавлять ноль в начале шифра и корректно отрабатывать арифметическую прогрессию с подобным шифром.
AKBAMAPUH
01-10-2012, 22:45
Как вариант, перед заменой текста закладок сохранять в переменных/массивах начала и концы (Start и End) свойств Range закладок и потом создавать новые объекты Range и закладки на их основе в сохранённых местах. »
пока найти не могу, но смысл там был вот какой - расставлялись 2 закладки (начало и конец) в нужное место и потом осуществлялось выделение текста между этими закладками и вставка необходимого текста в это выделение.
завтра продолжу поиск - сейчас уже спать...
AKBAMAPUH
02-10-2012, 21:18
вот нашёл дуплексная печать (http://support.microsoft.com/kb/230743)
безумное количество букв и абсолютно мне непонятно....
AKBAMAPUH
03-10-2012, 22:27
Option Explicit
Private Sub CommandButton1_Click()
Dim lNumber As Long
Dim i As Long
'Помещаем в переменную lNumber, с какого номера
'должна начинаться нумерация бланков.
lNumber = Me.TextBox1.Value
'проверяем на согласие с условием
If CheckBox1.Value = False Then
'выводим сообщение
MsgBox "Ошибка!" & " " & "Необходимо принять условие."
Else
'Делаем столько витков цикла, сколько бланков необходимо вывести на печать.
For i = 1 To Me.TextBox2.Value Step 1
Dim oDoc As Document
Set oDoc = Application.Documents.Add("C:\Primer\TEMP\1.docm")
'Помещаем в закладку "bm_1" данные из переменной lNumber.
oDoc.Bookmarks("bm_1").Range.Text = "0" & CStr(lNumber + (i - 1))
'Помещаем в закладку "bm_2" данные из переменной lNumber.
oDoc.Bookmarks("bm_2").Range.Text = "0" & CStr(lNumber + (i - 1))
'Помещаем в закладку "bm_3" данные из переменной lNumber.
oDoc.Bookmarks("bm_3").Range.Text = "0" & CStr(lNumber + (i - 1))
'Помещаем в закладку "bm_4" данные из переменной lNumber.
oDoc.Bookmarks("bm_4").Range.Text = "0" & CStr(lNumber + (i - 1))
'Распечатываем.
ActivePrinter = "doPDF v7"
ActiveDocument.PrintOut
'Скрываем пользовательскую форму
UserForm1.Hide
'закрываем активный документ без сохранения изменений, поскольку после вставки
'текста произошла замена закладки
ActiveDocument.Close SaveChanges:=wdDoNotSaveChanges
Next i
End If
End Sub
Private Sub CommandButton2_Click()
'Выход из формы и закрытие окна документа при нажатии кнопки "ОТМЕНА"
On Error GoTo ErrLabel
'Закрываем форму
Unload Me
'Закрываем текущий документ
ActiveDocument.Close
ErrLabel:
End Sub
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'действия с полем первый номер бланка для подстановки
With Me.TextBox1
If Not IsNumeric(.Text) Or Len(.Text) < 6 Then 'если в поле введены не цифры и их число меньше 6, то
MsgBox "Ошибка!" & " " & "Введите 6 цифр номера задания" 'выводим сообщение
Cancel = True 'возвращаемся к полю
.Text = "" 'очищаем поле
.SetFocus
End If
End With
End Sub
Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'действия с полем общее количество необходимых бланков
With Me.TextBox2
If Not (TextBox2.Value = 1 Or TextBox2.Value = 2 Or TextBox2.Value = 50) Then
MsgBox "Ошибка!" & " " & "Введите значение равное 1, 2 или 50" 'выводим сообщение
Cancel = True 'возвращаемся к полю
.Text = "" 'очищаем поле
.SetFocus 'фокус на поле
End If
End With
End Sub
Вот такой замечательный и главное рабочий код появился у меня в ходе безумно долгой и кропотливой работы...
есть правда по-прежнему небольшие недочёты, которые вносят в некотором роде незавершённость данному проекту:
1 - двустороння печать реализована путём создания нового принтера, в свойствах печати которого выставлена принудительно двусторонняя печать и весь документ печатается исключительно через этот принтер.
А хотелось бы конечно иметь более универсальный проект, чтобы не приходилось дополнительно производить какие либо манипуляции с компом и его принтерами.
2 - по-прежнему не могу понять как реализовать правильное использования закладок (bookmarks), поскольку на текущий момент времени у меня происходит не вставка текста, а полная замена закладки на текст, поэтмоу приходится с каждым витком открывать документ снова и снова.
Вот нашёл казалось бы замечательную статью про закладки, но не могу понять что делать с ней и как изменить под свои условия - см. эту статью (http://word.mvps.org/FAQs/MacrosVBA/InsertingTextAtBookmark.htm)
3 - в момент открытия документа появляется UserForm1, если нажать на "крестик", то появляется вот это сообщение из кода проекта
MsgBox "Ошибка!" & " " & "Введите 6 цифр номера задания"
А хотелось бы, чтобы закрывалась UserForm1 и текущий открытый документ, то есть то событие, которое происходит сейчас при нажатии на CommandButton2 (см. код выше).
Либо как вариант чтобы отсутствовал тот самый "крестик" на форме =)
Помогите пожалуйста, осталось совсем немного...
2 - в статье по вашей ссылке есть подпрограмма обновления текста закладки UpdateBookmark, используйте её вместо прямого обновления. Вместо строк типа oDoc.Bookmarks("bm_1").Range.Text = "0" & CStr(lNumber + (i - 1)) нужно вызывать её вот так UpdateBookmark "bm_1", "0" & CStr(lNumber + (i - 1)) 3 - установите точку останова (F9) где-нибудь в начале программы и отлаживайте по шагам (F8). Смотрите, что выполняется и в какой последовательности.
AKBAMAPUH
07-10-2012, 12:56
Dr.DG,
мне бы даже в голову не пришло, что простая вставка кода в форму решит вопрос с обновлением закладок, даже менять ничего не пришлось.
у меня теперь другие вопросы возникли:
1 - каким образом сделать UserForm1 незакрывающуюся? То есть чтобы на форме отсутствовал "крестик", либо чтобы на UserForm1 "крестик" был неактивным, затемнен. Хотя лучше конечно чтобы он просто-напросто отсутствовал.
2 - каким образом осуществить закрытие приложения Word?
указанный ниже код не закрывает приложение...
Word.Application.Quit
AKBAMAPUH
07-10-2012, 13:48
по поводу первого пункта нашёл замечательную вещь, но абсолютно в ней не могу разобраться, поскольку кода очень много для меня, мне столько не переварить...
мне необходим либо вариант "меню", либо вариант "крестик" (см. пример во вложении)
подскажите какой код выдернуть из примера и куда его вставить, пожалуйста.
AKBAMAPUH
07-10-2012, 21:25
по поводу пункта 2 - возникло недоразумение из-за того, что сначала выполнялась процедура закрытия текущего активного документа, а потом осуществлялась попытка закрыть приложение Word, но в этом и есть абсурдность ситуации, потому что уже некому и нечему выполнять код =)
я думаю, что верно понял этот момент. получается, что эту ситуацию необходимо оставить как есть.
хотя если есть у кого комментарии - высказывайтесь, может есть другое решение вопроса.
всё ещё жду решение вопроса по пункту 1.
спасибо за внимание.
AKBAMAPUH, ничто не мешает сохранить документ/документы и воспользоваться сразу «Application.Quit» без «Document.Close». Либо просто использовать потребным образом первый аргумент — «SaveChanges» — метода «Application.Quit»: Quit Method (http://msdn.microsoft.com/en-us/library/office/aa220368(v=office.11).aspx).
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.