1

Тема: Имя файла из фрагментов документа

Мои навыки в макросописании пока очень слабы, а реальная задача уже есть.
В шаблоне документа есть таблица, в некоторых ячейках которой размещены элементы управления типа "Обычный текст". По умолчанию в них показан замещающий текст, который предполагается заменить конкретными живыми данными.
Задача в том, чтобы напомнить пользователю о том, что некоторые поля незаполнены при сохранении (и дать возможность вернуться к редактированию), и что самое важное — предложить имя файла при сохранении, состоящее из железно заданного префикса и содержимого некоторых элементов, конкретно — "ТЗ [Имя заказчика] [Предмет заказа]".
Для редактирования пользователями закрыт весь документ, кроме некоторых полей, поэтому структура его меняться не будет. Я пробовал пользоваться передачей данных из свойств документа в имя файла, но не смог назначить передачу данных из конкретных полей.  Если будет небходимость — приложу сам шаблон.
Помогите, пожалуйста!

2

Re: Имя файла из фрагментов документа

Выложите файл

3

Re: Имя файла из фрагментов документа

Выкладываю файл.
Защита отключена, часть элементов, не имеющих отношения к задаче, убрана.
Итоговое имя файла должно содержать "ТЗ" и содержимое элементов управления Заказчик и Макет — "ТЗ Газпром спички".

4

Re: Имя файла из фрагментов документа

Странно, файл не вложился в прошлый раз. Пробую ещё раз.
В предпросмотре не видно. Выкладаю в дропбокс и даю ссылку:
внешняя ссылка

5

Re: Имя файла из фрагментов документа

Нашел не очень красивое решение задания имени файла при сохранении с помощью макроса для вашего случая (поскольку элемент управления "Заказчик" имеет номер 1 в коллекции элементов управления, а элемент управления "Макет" имеет номер 2):

    Dim strS As String
    strS = "ТЗ" & " " & ActiveDocument.ContentControls(1).Range.Text & " " & ActiveDocument.ContentControls(2).Range.Text
    ActiveDocument.SaveAs2 FileName:=strS

Надеюсь, что эксперт aap77 предложит более универсальное и красивое решение.

Удобной и приятной работы в Word!
Перевести спасибо на Яндекс кошелёк - 41001162202962; на WebMoney - R581830807057.

6

Re: Имя файла из фрагментов документа

Это решение получше, но тоже недостаточно хорошее.

Предварительно нужно назвать первый элемент управления "Заказчик", а второй - "Макет" (это можно сделать с помощью функции Свойства в группе Элементы управления на вкладке Разработчик).

    Dim strS As String
    Dim strS1 As String
    Dim strS2 As String
    Dim s As ContentControl
    For Each s In ActiveDocument.ContentControls
        If s.Title = "Заказчик" Then strS1 = s.Range.Text
        If s.Title = "Макет" Then strS2 = s.Range.Text
    Next
    strS = "ТЗ" & " " & strS1 & " " & strS2
    ActiveDocument.SaveAs2 FileName:=strS

Вероятно, есть возможность непосредственно обратиться к элементу управления по имени.

Удобной и приятной работы в Word!
Перевести спасибо на Яндекс кошелёк - 41001162202962; на WebMoney - R581830807057.

7

Re: Имя файла из фрагментов документа

1. Макет не доработан сам по себе. Чтобы пользователю можно было сообщить о незаполненных полях надо сначала и обозвать. Это можно сделать сделать с помощью макроса

Public Sub TitleControl()
Dim Control As ContentControl
Dim Table As Table
Dim CellTitle As Cell, NumCell As Long, Rng As Range, Title As String
    Set Table = ActiveDocument.Tables(1)
    Table.ID = "DB"
        For Each Control In ActiveDocument.ContentControls
            If Control.Title = "" and Control.Range.Tables.Count = 1 And Control.Range.Tables(1).ID = "DB" Then
                Set CellTitle = Control.Range.Cells(1)
                Set Rng = ActiveDocument.Range(Table.Range.Start, CellTitle.Range.End)
                NumCell = Rng.Cells.Count - 1
                Title = Mid(Table.Range.Cells(NumCell).Range.Text, 1, _
                    Len(Table.Range.Cells(NumCell).Range.Text) - 3)
                Control.Title = Title
                Control.Tag = Title
            End If
        Next Control
End Sub

Данный макрос присваивает таблице 1 документа идентификатор "DB" и присваивает полям названия в виде текста, находящегося в ячейке слева.
Теперь мы создадим свойство Controls As Collection, которое будет в себя включать все поля таблицы

Public Property Get Controls() As Collection
Dim Control As ContentControl
    Set Controls = New Collection
        For Each Control In ActiveDocument.ContentControls
            If Control.Range.Tables.Count = 1 And Control.Range.Tables(1).ID = "DB" Then
                Controls.Add Control, Control.Title
            End If
        Next Control
End Property

2. Далее мы создадим функцию colControlsNotValue() As Collection
Эта функция возвращает коллекцию незаполненых полей

Private Function colControlsNotValue() As Collection
Dim Control As ContentControl, i As Long
    Set colControlsNotValue = New Collection
        For i = 1 To Controls.Count
            Set Control = Controls(i)
            If Control.ShowingPlaceholderText = True Then
                colControlsNotValue.Add Control, Control.Title
            End If
        Next i
End Function

3. Теперь создадим процедуру, которая будет извещать пользователя о незаполненых полях
Для чего в модуле где хранится записанный ранее код создадим переменнную

Public ControlsNotValue As Collection

И собственно код процедуры.

Public Sub InfoControlsNotValue()
Dim Control As ContentControl, i As Long
Dim info As String
Set ControlsNotValue = colControlsNotValue
info = "Всего не заполнено полей: " & ControlsNotValue.Count & Chr(13)
info = info & "Поля: " & Chr(13)
    For i = 1 To ControlsNotValue.Count
        Set Control = ControlsNotValue(i)
            info = info & Control.Title & Chr(13)
    Next i
    MsgBox info, vbOKOnly + vbInformation, "Не заполненные поля"
End Sub

Ну и остается написать код сохранения документа

8

Re: Имя файла из фрагментов документа

chegr
Выкладываю переработанный шаблон для тестирования
В нем незаполненные поля отмечаются красным цветом.
А при сохранении выводится информация о количестве незаполненых полей и их имена.
Шаблон не трудный, но можно некоторые моменты улучшить
Пишите

Post's attachments

Blank TZ.dotm 39.67 Кб, 5 скачиваний с 2012-07-19 

You don't have the permssions to download the attachments of this post.

9

Re: Имя файла из фрагментов документа

Alex_Gur
Спасибо! Именно такое решение я себе и представлял в голове, как фактическое решение проблемы. Порядок контролов не меняется, поэтому можно к ним стучаться по порядковым номерам, с единицы, потому что VB :) С моей точки зрения первое даже лучше, чем второе, потому что сразу знает куда стучаться, не пользуется перебором и легко правится в случае чего. Второй вариант рассчитан на возможное изменение порядка элементов, но если такое случится, я наверняка буду трогать и макрос. Зато он не рассчитан на изменение названия элемента управления :) То, что их можно называть, я нашёл уже вчера, после отправки сообщения. И мне
aap77
Спасибо! Благодаря комментариям, у меня получилось разобрать в незнакомом, по сути, синтаксисе и понять механизм работы. Решение получилось сверхуниверсальное и всеохватывающее. Поддерживать его работоспособность в случае изменения мне, правда, сложновато будет, но хотя бы часть его я освоить смогу.
Я попробовал ваш вариант шаблона. Он запаролен, прежде всего, что не сильно критично. И, к сожалению, работает не так, как предполагалось. Я далеко не сразу заметил кнопку Сохранить :) К сожалению, это автоматически означает, что её не заметят и менеджеры, которые будут работать с бланком; даже елси я им ткну в неё, они по привычке будут пользоваться старым механизмом сохранения, и будут совершенно правы. Нажатие же обычной кнопки не подставляет в имя файла ничего.
Подсветка полей красным — это гениальная идея для такого шаблона. Пожалуй, с такой подсветкой даже потенциально раздражающее окно со списком незаполненных полей совершенно ни к чему. Иногда случается, что некоторые поля могут быть пустыми; например, если нет никаких материалов к заказу, или если размеры произвольны, или ещё что-нибудь. Бланк нужен для упорядочивания такой информации, а не для создания сверхжёстких рамок — поэтому организация поля "размеры", в частности, чрезмерна в своей навязчивости, одним аккордом его на заполнить.
Кнопка назначения пути для папки хранения материалов у меня просто неактивна. Опять же, заново искать папку, которая, скорее всего, открыта параллельно с правкой бланка, вряд ли будет удобно. А вот скопировать путь из строки адреса они точно уже умеют.  В вашем же варианте задать его вручную нельзя.
В общем, я дизайнер, мне совершенно нечего сказать вам по организации кода, только по юзабилити :)

Ещё раз всем спасибо, этого должно хватить. Если ещё будут вопросы, приду в эту же тему.

10

Re: Имя файла из фрагментов документа

Alex_Gur,
при внедрении первого решения, что может означать ошибка Invalid Outside Procedure  с указанием присваивания "ТЗ" первым фрагментом строки?
Попробуйте использовать этот же фрагмент кода в произвольном шаблоне, тоже такое же будет?

11

Re: Имя файла из фрагментов документа

1. По поводу пароля снять его наберите 1977.
2. Я показал только некоторые способы решения Вашей проблемы.
3. По поводу кнопки Сохранить  файл, если она Вам не нужна удалите ее, но оставьте код. Во вложении я добавил событие appWD_DocumentBeforeSave, которое срабатывает перед сохранением файла и назначил ему код кнопки Сохранить  файл
4. По заблокированной кнопке Обзор, я специально не стал писать для нее код, потому что почти идентичен разблокированной кнопке и для более лучшего понимания Вы можете написать код сами. Если эти кнопки Вам не нужны удалите их и вводите пути вручную. Правда можно улучшить шаблон, написав для полей код запоминания предыдущих путей.

Post's attachments

Blank TZ.dotm 43.1 Кб, 4 скачиваний с 2012-07-20 

You don't have the permssions to download the attachments of this post.

12

Re: Имя файла из фрагментов документа

Точно, я нахрапом не сразу сообразил, что код кнопке просто не прописан. Буду ковырять на выходных свой вариант. Запоминание путей было бы кстати, но в данном случае не подойдёт — шаблон будет лежать в сетевой папке, пользователей будет много, а пути чаще всего уникальны от случая к случаю. Ещё раз спасибо — вы мне здорово помогли.

13

Re: Имя файла из фрагментов документа

chegr пишет:

Alex_Gur,
при внедрении первого решения, что может означать ошибка Invalid Outside Procedure  с указанием присваивания "ТЗ" первым фрагментом строки?
Попробуйте использовать этот же фрагмент кода в произвольном шаблоне, тоже такое же будет?

Трудно сказать, в чем дело. Наиболее вероятная причина ошибки  Invalid Outside Procedure - помещение кода внутри модуля вне процедуры.

В произвольном шаблоне, в котором отсутствуют элементы управления, будет выдаваться ошибка, связанная с отсутствием этих элементов. Я добавил обработку ошибки.

Попробуйте еще раз вставить в модуль всю процедуру:

Sub SaveTZ()
'
  On Error GoTo ErrorHandler
    Dim strS As String
    strS = "ТЗ" & " " & ActiveDocument.ContentControls(1).Range.Text & " " & ActiveDocument.ContentControls(2).Range.Text
    ActiveDocument.SaveAs2 FileName:=strS
   GoTo Ends:
ErrorHandler:
  MsgBox ("В документе отсутствуют два элемента управления!")
Ends:
End Sub
Удобной и приятной работы в Word!
Перевести спасибо на Яндекс кошелёк - 41001162202962; на WebMoney - R581830807057.