Чем я занимаюсь
Через DDE я отправляю в свой макрос слова некоторые имена полей.
С этими именами полей макрос создает поля типа «wdFieldFillIn».
Текущая проблема, с которой я сталкиваюсь, начинается с document.Fields.Add-Function.
Потому что каждый FillInField предлагает пользователю ввести значение. Но я не хочу, чтобы пользователь вводил значение сейчас, вместо этого он должен просто создать эти поля, не показывая никаких подсказок.
Чтобы упростить сценарий в показанном примере, вы видите, как я добавляю один FillInField при выборе курсора.
Dim myRange As Range: Set myRange = Selection.Range
Dim FillInField As Field: Set FillInField = doc.Fields.Add( _
Range:=selectedRange, _
Type:=wdFieldFillIn, _
Text:=fieldName)
Что я пробовал до сих пор:
Отправка нажатий клавиш через SendKeys "{ESCAPE}"
Результат: срабатывает слишком поздно, потому что макрос ждет подсказки.
Запись в виде обычного текста: { FILLIN My_Fieldname \* MERGEFORMAT }
Результат: Не обрабатывается как поле.
Окно подсказки:
Реализованное решение используется
Это решение относится к ответу @jonsson и работает для моего варианта использования.
Dim FillInField As Field: Set FillInField = Selection.Fields.Add(_
Range:=insertRange, _
Type:=wdFieldEmpty, _
Text:=fieldName)
FillInField.code.Text = "FILLIN " & fieldName & " \* MERGEFORMAT "
FillInField.Result.Text = fieldExampleText
Set FillInField = Nothing
В результате заполняется поле без запроса пользователя во время его добавления.\
@Ike Да, я думал об элементах управления содержимым, но поля для заполнения также совместимы с LibreOffice. Это значительно упростило реализацию в моем C++-коде.
@jonsson Я только что проверил то, что вы сказали, когда .Text = "" в порядке, он действительно добавляет пустое поле в документ, однако спрашивающему нужно wdFieldFillIn, а свойство Type доступно только для чтения Это не так. можно указать его значение позже, и когда .Text= "FILLIN My_Fieldname", тогда все равно будет отображаться "окно подсказки".
@jonsson Согласно официальному документу (ссылку я давал ранее) и фактически проверенному, после того как вы указали Type=wdFieldEmpty с помощью метода Add, если вы попытаетесь присвоить ему новое значение позже, вы получите сообщение об ошибке во время компиляции, в котором говорилось, что вы не можете присвоить значение свойству только для чтения.
@jonsson Я не понимаю, о чем вы говорите, и у меня ограниченные знания о полевых объектах. Почему бы вам не сделать код, чтобы проверить это вместе? Это лучше, не так ли? Спокойной ночи (я в Тайбэе) и приятно познакомиться.
@jonsson Хорошо, я попробую позже. Если возникнут вопросы, я вернусь, чтобы прокомментировать здесь. СПАСИБО.
@OscarSun Я попробовал решение Джонссона, и оно сработало для моего варианта использования. Это не подсказывает мне ничего при добавлении поля. Поле вроде работает правильно. Я добавил реализацию в свой рабочий код к вопросу.
@BaronvonHoot, вы приняли и установили Type:=wdFieldEmpty. Кажется, вам все равно, что на этом этапе выполнения Type должен быть wdFieldFillIn Хорошо. Я мало что знаю об этой реализации и не уверен, какую операцию вы пытаетесь выполнить. Я просто высказываю свое мнение. Если вы смогли удовлетворить текущие потребности, то я очень рад за вас; возможно, у меня будут подобные потребности в будущем, я также вернусь, чтобы наблюдать за ссылкой. СПАСИБО.





Боюсь, то, что вы хотите, невозможно, пока вы используете поле «Заполнить», потому что по умолчанию оно определено для запуска окна сообщения (как вы сказали «окно подсказки»), которое должно быть введено пользователем. Вы можете установить значение по умолчанию только для ввода в VBA или в пользовательском интерфейсе, параметр "\d" используется в текстовом аргументе, но нет настройки, чтобы не отображать это окно сообщения.
fieldName = "\d """ '"" is what the default string value you want
Поскольку это окно сообщения открыто как эксклюзивная форма ( модальная ), выполнение кода VBA будет прервано. Если вы хотите выполнить что-то еще в VBA, возможно, вы можете попытаться создать UserForm и установить событие Timer и включить его в фоновом режиме, прежде чем выполнять метод .Add, UserForm, а затем запустить SendKeys в указанном месте. время. И насколько я знаю, многопоточность нельзя реализовать только на VBA
Вы можете обратиться к этой статье:
Это решение сработало. Но вылилось в мигание всплывающих окон, которые появлялись ненадолго. Кроме того, если пользователь был достаточно быстр, он все еще мог ввести что-то в приглашение.
@BaronvonHoot Вы имеете в виду использование методов UserForm TimerEvent и SentKeys? Может ли это сократить временной интервал таймера или открыть пользовательскую форму в фоновом режиме, например, установить для свойства visible значение false или установить аргумент open для скрытия (например, использовать метод Load вместо использования метода Show для запуска формы. Возможно, всплывающее окно, которое вы означает только то окно подсказки, которое вы хотите пропустить, и я неправильно понял.
AIUI вы пытаетесь вставить поле FILLIN, фактически не выполняя его, чтобы вы могли выполнить его позже. НО, если это не так, возможно, вы могли бы уточнить.
Если это так, одним из способов было бы вставить его как «Пустой тип поля», а затем изменить его код поля следующим образом.
Dim f as Word.Field
Set f = Selection.Fields.Add(wdFieldEmpty,"")
f.Code.Text = " FILLIN My_FieldName " ' or whatever code you actually need
Set f = Nothing
Затем, когда поле действительно выполняется (как бы это ни было сделано), оно будет вести себя как обычный FILLIN.
Если вы хотите, чтобы поле было вставлено так, чтобы оно имело результат независимо от того, выполняется заполнение или нет, вам нужно сделать немного больше, потому что, например
Dim f as Word.Field
Set f = Selection.Fields.Add(wdFieldEmpty,"")
f.Code.Text = " FILLIN My_FieldName " ' or whatever code you actually need
f.Result.Text = "the text I want in the result"
Set f = Nothing
фактически вставит текст "после" результата поля. Но в этом случае все, что вам действительно нужно сделать, это вставить поле, которое имеет результат, и изменить его код, например.
Dim f as Word.Field
Set f = Selection.Fields.Add(wdFieldQuote,"the text I want in the result")
f.Code.Text = " FILLIN My_FieldName " ' or whatever code you actually need
Set f = Nothing
@OscarSun поднял вопрос о том, что свойство .Type объекта Word Field доступно только для чтения, поэтому вы не можете
Dim f as Word.Field
Set f = Selection.Fields.Add(wdFieldQuote,"the text I want in the result")
f.Type = wdFieldFillin
поскольку компилятор отметит попытку присвоения свойству только для чтения. И это правильно. ИМО, это наблюдение заслуживает небольшого пояснения.
Если вы используете следующий код, все может стать яснее:
Sub insertfillin()
Dim f As Word.Field
Debug.Print "wdFieldQuote = " & CStr(WdFieldType.wdFieldQuote)
Debug.Print "wdFieldFillin = " & CStr(WdFieldType.wdFieldFillin)
Set f = Selection.Fields.Add(Selection.Range, WdFieldType.wdFieldQuote, "temp result")
' This should be the same as WdFieldType.wdFieldQuote
Debug.Print "New field's type = " & CStr(f.Type)
f.Code.Text = "FILLIN MyFieldName"
' This should be the same as WdFieldType.wdFieldFillin
Debug.Print "Field type is now " & CStr(f.Type)
Set f = Nothing
End Sub
то есть мы на самом деле не пытались присвоить f.Type, поэтому компилятор не будет жаловаться. Возможно, с точки зрения программирования лучше всего видно, что изменение типа поля является побочным эффектом изменения его кода и, по-видимому, было бы запрещено, если бы, например, мы использовали функциональный язык программирования.
Вы думали об использовании элементов управления содержимым вместо полей. Тогда у вас не будет этих проблем.