Ошибка при вызове метода контекста execute слишком длинный строковый параметр

Заполняю договор в ворде из 1С.

    Документ = ПолучитьCOMОбъект(«»,»Word.Application»);

    Документ.Documents.Open(Константы.ИмяШаблонаДоговора.Получить());

    //Документ.ActiveDocument;

    Замена = Документ.ActiveDocument.Range().Find;

    Замена.Execute(«пНомерДоговора», Ложь, Истина, Ложь, , , Истина, , Ложь, ОбщегоНазначения.ПолучитьНомерНаПечать(ЭтотОбъект));

    Замена = Документ.ActiveDocument.Range().Find;

    Замена.Execute(«пДатаДоговора», Ложь, Истина, Ложь, , , Истина, , Ложь, Формат(Дата, «ДЛФ=DD»));

    Замена = Документ.ActiveDocument.Range().Find;

    Замена.Execute(«пТуристы», Ложь, Истина, Ложь, , , Истина, , Ложь, ПолучитьТекстТуристов());

Проблема возникает с третьей заменой, так как ПолучитьТекстТуристов() возвращает длинную строку.

Как можно решить задачу?

Слишком длинный строковый параметр.

Автор Rust, 03 апр 2017, 07:42

0 Пользователей и 1 гость просматривают эту тему.

Здравствуйте!
При замене текста в word(execute),использовав более 255 символов-ошибка: Слишком длинный строковый параметр.

Как разбить строку на части?


Цитата: Rust от 03 апр 2017, 07:42
Здравствуйте!
При замене текста в word(execute),использовав более 255 символов-ошибка: Слишком длинный строковый параметр.

Как разбить строку на части?

Гугл выдал следующее:
цитата «Разбиваешь вставляемую строку на строку с количеством символов 255-ДлинаСтроки(«{«+Элемент.Ключ+»}»)
потом к каждой отрезанной части перед вставкой в ворд дописываешь «{«+Элемент.Ключ+»}» вот и всё.
Таким образом у тебя цикл будет постоянно находить ту часть, которую надо заменить твоим длинным текстом и по кускам ты его заменишь»
Не знаю можно ли тут кидать ссылки на другие сайты, поэтому рекомендую самостоятельно погуглить.
Не помощь, но зато совет :)


Цитата: Norfolk от 03 апр 2017, 07:57

Цитата: Rust от 03 апр 2017, 07:42
Здравствуйте!
При замене текста в word(execute),использовав более 255 символов-ошибка: Слишком длинный строковый параметр.

Как разбить строку на части?

Гугл выдал следующее:
цитата «Разбиваешь вставляемую строку на строку с количеством символов 255-ДлинаСтроки(«{«+Элемент.Ключ+»}»)
потом к каждой отрезанной части перед вставкой в ворд дописываешь «{«+Элемент.Ключ+»}» вот и всё.
Таким образом у тебя цикл будет постоянно находить ту часть, которую надо заменить твоим длинным текстом и по кускам ты его заменишь»
Не знаю можно ли тут кидать ссылки на другие сайты, поэтому рекомендую самостоятельно погуглить.
Не помощь, но зато совет :)

Большое спасибо!Встречал этот вариант.Но,не понимаю как это реализовать.Поэтому обратился сюда :dfbsdfbsdf:

Добавлено: 03 апр 2017, 09:36


ЗаменаКонтента.Execute(«[Комментарий1Замена]»,,,,,,,,,Комментарий1,2);


свой код работы с Вордом выкладывайте, (тот код где возникает ошибка +/- десяток команд
тогда можно будет подсказать конкретнее.

если помогло нажмите: Спасибо!


WordApplication = Новый COMОбъект("WORD.Application");
WordApplication.DisplayAlerts = 0;   // не выводить предупреждения

Зак = WordApplication .Documents.Add(ПутьКЗаключению);


Комментарий1=Док.Комментарий1;

ЗаменаКонтента = Зак.content.Find;

ЗаменаКонтента.Execute("[Комментарий1Замена]",,,,,,,,,Комментарий1,2);


Не дает вставить более 255 символов.
Знаю что нужно разбить эту строку,(Как в совете выше) Но незнаю как.

Добавлено: 03 апр 2017, 10:06


Цитата: LexaK от 03 апр 2017, 09:44
свой код работы с Вордом выкладывайте, (тот код где возникает ошибка +/- десяток команд
тогда можно будет подсказать конкретнее.

WordApplication = Новый COMОбъект("WORD.Application");
WordApplication.DisplayAlerts = 0;   // не выводить предупреждения

Зак = WordApplication .Documents.Add(ПутьКЗаключению);


Комментарий1=Док.Комментарий1;

ЗаменаКонтента = Зак.content.Find;

ЗаменаКонтента.Execute("[Комментарий1Замена]",,,,,,,,,Комментарий1,2);


Не дает вставить более 255 символов.
Знаю что нужно разбить эту строку,(Как в совете выше) Но незнаю как.


попробуйте так, должно сработать


WordApplication = Новый COMОбъект("WORD.Application");
    WordApplication.DisplayAlerts = 0;   // не выводить предупреждения

            Зак = WordApplication .Documents.Add(ПутьКЗаключению);

        Комментарий1=Док.Комментарий1;

        ЗаменаКонтента = Зак.content.Find;

            //заменено на цикл, ниже
        //ЗаменаКонтента.Execute("[Комментарий1Замена]",,,,,,,,,Комментарий1,2);

//разбивка замены по 200 символов
лкВсяДлина = СтрДлина(Комментарий1);
лкТекущаяПозиция = 1;
лкКлюч = "[Комментарий1Замена]";
Пока лкТекущаяПозиция < лкВсяДлина Цикл
лкЧасть = Сред(Комментарий1, лкТекущаяПозиция, 200) + лкКлюч;
        ЗаменаКонтента.Execute(лкКлюч,,,,,,,,,лкЧасть,2);
лкТекущаяПозиция = лкТекущаяПозиция + 200;
КонецЦикла;

//так как у вас ключ текстовый - чистим ключ
        ЗаменаКонтента.Execute(лкКлюч,,,,,,,,,"",2);

если помогло нажмите: Спасибо!


Цитата: LexaK от 03 апр 2017, 10:13
попробуйте так, должно сработать
WordApplication = Новый COMОбъект("WORD.Application");
    WordApplication.DisplayAlerts = 0;   // не выводить предупреждения

            Зак = WordApplication .Documents.Add(ПутьКЗаключению);

        Комментарий1=Док.Комментарий1;

        ЗаменаКонтента = Зак.content.Find;

            //заменено на цикл, ниже
        //ЗаменаКонтента.Execute("[Комментарий1Замена]",,,,,,,,,Комментарий1,2);

//разбивка замены по 200 символов
лкВсяДлина = СтрДлина(Комментарий1);
лкТекущаяПозиция = 1;
лкКлюч = "[Комментарий1Замена]";
Пока лкТекущаяПозиция < лкВсяДлина Цикл
лкЧасть = Сред(Комментарий1, лкТекущаяПозиция, 200) + лкКлюч;
        ЗаменаКонтента.Execute(лкКлюч,,,,,,,,,лкЧасть,2);
лкТекущаяПозиция = лкТекущаяПозиция + 200;
КонецЦикла;

//так как у вас ключ текстовый - чистим ключ
        ЗаменаКонтента.Execute(лкКлюч,,,,,,,,,"",2);

Спасибо!Помогло!:)


Цитата: LexaK от 03 апр 2017, 10:13
попробуйте так, должно сработать
WordApplication = Новый COMОбъект("WORD.Application");
    WordApplication.DisplayAlerts = 0;   // не выводить предупреждения

            Зак = WordApplication .Documents.Add(ПутьКЗаключению);

        Комментарий1=Док.Комментарий1;

        ЗаменаКонтента = Зак.content.Find;

            //заменено на цикл, ниже
        //ЗаменаКонтента.Execute("[Комментарий1Замена]",,,,,,,,,Комментарий1,2);

//разбивка замены по 200 символов
лкВсяДлина = СтрДлина(Комментарий1);
лкТекущаяПозиция = 1;
лкКлюч = "[Комментарий1Замена]";
Пока лкТекущаяПозиция < лкВсяДлина Цикл
лкЧасть = Сред(Комментарий1, лкТекущаяПозиция, 200) + лкКлюч;
        ЗаменаКонтента.Execute(лкКлюч,,,,,,,,,лкЧасть,2);
лкТекущаяПозиция = лкТекущаяПозиция + 200;
КонецЦикла;

//так как у вас ключ текстовый - чистим ключ
        ЗаменаКонтента.Execute(лкКлюч,,,,,,,,,"",2);

Если в Док.Комментарий1 будет один символ, то не сработает. Надо

Пока лкТекущаяПозиция <= лкВсяДлина Цикл


I recognize that this is a year old but since the technical side of the question never got answered I figured I take the time to post this for who ever stumbles upon it.

You could do something like this of you really must do it this way.

FindAndReplace(word, replacementKey, SequentialReplaceToken);
var restOfText = replaceWithText;
while (restOfText.Length > 20)
{
    var firstTwentyChars = restOfText.Substring(0, 20);
    firstTwentyChars += SequentialReplaceToken;
    restOfText = restOfText.Substring(20);
    FindAndReplace(word, SequentialReplaceToken, firstTwentyChars);
}
FindAndReplace(word, SequentialReplaceToken, restOfText);

FindAndReplace(…) being a wrapper over the Word interop Function.
Like so:

private void FindAndReplace(Application doc, object findText, object replaceWithText)
{
    //options
    object matchCase = false;
    object matchWholeWord = true;
    object matchWildCards = false;
    object matchSoundsLike = false;
    object matchAllWordForms = false;
    object forward = true;
    object format = false;
    object matchKashida = false;
    object matchDiacritics = false;
    object matchAlefHamza = false;
    object matchControl = false;
    object read_only = false;
    object visible = true;
    object replace = 2;
    object wrap = 1;
    //clear previous formatting
    doc.Selection.Find.ClearFormatting();
    //execute find and replace
    doc.Selection.Find.Execute(ref findText, ref matchCase, ref matchWholeWord,
        ref matchWildCards, ref matchSoundsLike, ref matchAllWordForms, ref forward, ref wrap, ref format, ref replaceWithText, ref replace,
        ref matchKashida, ref matchDiacritics, ref matchAlefHamza, ref matchControl);
}

And SequentialReplaceToken being a string constant that is known to never come up in the document.

Трудовой договор

Для большенства организаций стандартная печатная форма трудового договора в программе 1С:Зарплата и управление персоналом не подходит. Фирма 1С, в восьмой версии своей программы, любезно предусмотрела возможность добавлять дополнительные печатные формы для документов и других объектов. Воспользуемся данной возможностью и создадим трудовой договор, который будет открываться в Microsoft Word.

Специалисты по конфигурированию могут разрабатывать внешние обработки вне конфигурации, используемой в организации. Разработанный отчет или обработка передается в виде файла так называемой внешней обработки с расширением .epf. Пользователь может подключить эту обработку к конфигурации самостоятельно.

Сведения о подключенных обработках хранятся в справочнике «Внешние обработки». Чтобы подключить новую внешнюю обработку, нужно зарегистрировать ее в указанном справочнике.

Технические требования к внешней печатной форме

Внешняя обработка должна содержать:

  • Реквизит «СсылкаНаОбъект», куда при вызове будет передана ссылка на объект, для которого необходимо выполнить печать;
  • Необязательный реквизит «ДополнительныеПараметры» произвольного типа, которому будут передаваться дополнительные параметры примитивного типа в виде структуры;
  • Функция Печать() — без параметров,  возвращающая табличный документ;
  • Также внешняя печатная обработка может иметь в своем составе макет «Параметры_Авторегистрации», используемый для автоматического заполнения принадлежности печатной формы в справочнике «Внешние обработки» и состоящий из двух колонок: «Полное имя метаданного» и «Имя табличной части».

Создание внешней обработки

Запустим 1С:Предприятие в режиме «Конфигуратор» и через меню «Файл» — «Новый» создадим внешнюю обработку.

Создание внешней обработки

Создадим реквизит «СсылкаНаОбъект». Для этого нажимем кнопку «Добавить» или клавишу «Insert» и заполним свойства. В зависимости от того, для каких объектов будет использоваться эта печатная форма, нужно выбрать тип. В нашем случае, внешняя печатная форма будет использоваться только для справочника «Сотрудники организации», поэтому укажем соответствующий тип «СправочникСсылка.СотрудникиОрганизаций».

Свойства реквизита

Реквизит «ДополнительныеПараметры» нам не понадобится. Создадим экспортную функцию Печать() («Действия» — «Открыть модуль объекта»).

 Функция Печать()

Прежде чем написать тело этой функции, создадим макет, который она будет возвращать.

Макет трудового договора в формате Microsoft Word

Существует, по меньшей мере, три способа создания шаблона.

Первый. В тексте документа содаются метки особого формата, например, «м_НомерДоговора», затем, в модуле обработки производится поиск и замена значений.

Второй способ. В документе Word создаются закладки, к которым потом можно обращаться по имени. Минус этого способа в том, что метка должна быть уникальна, т.е., например, если нужно вставить фамилию сотрудника в каждый абзац текста, то придется сделать несколько закладок с разными именами.

Способ три. В шаблон добавляются служебные поля, например, «DocVariable» или «Author». Используя DocVariable можно обращаться к переменной по имени, например, «ДокументВорд.Variables.Add(ИмяПеременной, ЗначениеПеременной);», но ее не видно в шаблоне. Поле «Author» отображается в шаблоне, но обращаться к нему придется в цикле по индексу: «ДокументВорд.Fields.item(Индекс).Result.Text = Значение;».

На мой взгляд, первый способ является самым оптимальным. Шаблон документа легко редактируется, метки видны в тексте, для создания меток не нужны сложные вставки. Поэтому будем делать шаблон именно этим способом.

Откроем программу Microsoft Office. Для примера добавим лишь одну строку: «Трудовой договор № [НомерДоговора]».

Сохраним шаблон.

Добавим получившийся шаблон в нашу обаботку. Для этого выбираем «Макеты» и нажимаем кнопку «Добавить» или клавишу «Insert».

Выбор макета трудового договора

Откроется конструктор запроса, в котором выберем тип «Active Document» и файл шаблона.

Конструктор макета Active Document

Функция Печать()

Вернемся к функции, которую мы создали ранее. Настало время написать ее тело.

// Предопределенная функция для внешних печатных форм
//
Функция Печать() Экспорт// Получим объект Microsoft Word из макета
   
ОбъектВорд = ПолучитьМакет(«ТрудовойДоговор»).Получить();// Получим документ из объекта и активируем его
   
Документ = ОбъектВорд.Application.Documents(1);
   
Документ.Activate();// Поиск и замена маркеров
   
Замена = Документ.Content.Find;
   
Замена.Execute(«[НомерДоговора]», , , , , , , , , «007», 2);// Вывод документа
   
ОбъектВорд.Application.Visible = Истина;
   
ОбъектВорд.Activate();

КонецФункции

// Печать()

Из кода видно, что в файле шаблона производится поиск строки «[НомерДоговора]» и ее замена на строку «007».

Параметры авторегистрации

Для автоматического заполнения принадлежности печатной формы к объектам конфигурации, добавим еще один макет «Параметры_Авторегистрации». Это будет табличный документ, содержащий одну колонку с именами объектов метаданных, к которым будет принадлежать печатная форма. В нашем случае таблица будет выглядить следующим образом.

Параметры авторегистрации

Сохраним получившуюся внешнюю обработку.

Подключение дополнительных внешних печатных форм

Запустим 1С Предприятие. Откроем справочник «Дополнительные внешние печатные формы» через меню «Сервис» — «Дополнительные отчеты и обработки».

Нажмем кнопку «Добавить», затем зарегистрируем новую печатную форму, нажав «Заменить файл внешней обработки». Автоматически заполнится принадлежность печатной формы справочнику «Сотрудники». Выберем «Трудовой договор» в колонке «Заменяемая печатная форма» чтобы стандартная печатная форма более не использовалась.

Регистрация внешней печатной формы

В итоге справочник будет выглядить следующим образом.

Дополнительные внешние печатные формы

Проверка результата

Откроем любого работающего сотрудника и нажмем кнопку «Печать» — «Трудовой договор». Откроется документ Microsoft Word с трудовым договором под номером «007».

Трудовой договор в MS Word

Дальнейшее описывать не имет смысла. Думаю, не составит большого труда доработать функцию Печать() и макет договора.

Ozam

0 / 0 / 0

Регистрация: 13.03.2018

Сообщений: 14

1

1C 8.x

22.03.2018, 12:39. Показов 5028. Ответов 6

Метки c, word (Все метки)


Приветствую. Есть шаблон для печати и значение (в данном случае «ПолноеНаименование») имеющее более 255 символов нужно сделать так чтобы данное значение выводились в таблицу. Код предоставляю:

Код шаблона Word

1C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
Договор=РеквизитФормыВЗначение("Объект").ПолучитьМакет("Договор");
    // Получить объект из макета.
    MSWord = Договор.Получить();
    Попытка
        Документ = MSWord.Application.Documents(1);
        Документ.Activate();
        // Получить объект, который будем использовать для поиска и замены.
        Замена = Документ.Content.Find;
        // Заменить заранее определенные ключевые конструкции на требуемый текст.     
            Если MSWord.Bookmarks.Exists("Таблица1") Тогда
         
        //Выделяем обязательную закладку начала таблицы
        MSWord.Bookmarks("Таблица1").Select();
         
         
        //Перемещаемся вниз, выделяем строку таблицы и копируем ее в буфер обмена
        MSWord.Application.Selection.MoveDown();
        MSWord.Application.Selection.SelectRow();
        MSWord.Application.Selection.Copy();
         
        Для Каждого ТекСтр ИЗ Объект.Счет Цикл
            Товар1=СокрЛП(ТекСтр.ПолноеНаименование);
            Цена1=СокрЛП(ТекСтр.Цена);
                     
            //Заменяем значения
            MSWord.Application.Selection.Find.Execute("Номер" ,,,,,,,,,Товар1,2);
            MSWord.Application.Selection.Find.Execute("Цена" ,,,,,,,,,Цена1,2);
            //Последний параметр поиска пустой
            //Перемещаемся вниз, вставляем из буфера обмена строку
            MSWord.Application.Selection.MoveDown();
            MSWord.Application.Selection.Paste();
            //Перемещаемся вверх и выделяем строку для замены значений
            MSWord.Application.Selection.MoveUp();
            MSWord.Application.Selection.SelectRow();
             
        КонецЦикла;
         
        //Вырезаем лишнюю строку
        MSWord.Application.Selection.Cut();
         
        //Скрываем обязательную закладку начала таблицы
        MSWord.Bookmarks("Таблица1").Select();
        MSWord.Application.Selection.TypeText(" ");
         
    КонецЕсли;
        
        // Делаем видимым приложение и активизируем его.       
        MSWord.Application.Visible = Истина;
        MSWord.Activate();
    Исключение
        // Если произойдет ошибка, выводятся данные об ошибке, и объект закрывается.
        Сообщение = Новый СообщениеПользователю();
        Сообщение.Текст = ОписаниеОшибки();
        Сообщение.Сообщить();  
        MSWord.Application.Quit();
    КонецПопытки;   
КонецПроцедуры  //Да-да-да код скомунизден

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

0

Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

22.03.2018, 12:39

Ответы с готовыми решениями:

Полное наименование товара в заявке
Здравствуйте. Есть документ Заявление о ввозе. В нем в Наименование добавляются товары из…

Массив записей. Структура: наименование товара, его количество, цену за единицу товара и общую стоимость данного товара
Пожалуйста помогите с задачкой на массивы для экзамена..
1.Разработать программу на ЯП Pascal, в…

Создать тип с описанием товара: код, наименование, цена за единицу товара, количество и сумма
Создать тип с описанием товара: код,наименование,цена за единицу товара,количество и сумма….

Создать тип с описанием товара: код, наименование, цена за единицу товара, количество и сумма.
Помоготе решить задачу плз!!!

Создать тип с описанием товара: код, наименование, цена за…

6

Тест

Эксперт 1С

383 / 162 / 56

Регистрация: 26.02.2010

Сообщений: 1,241

22.03.2018, 12:55

2

А в чем собственно проблема то?

0

0 / 0 / 0

Регистрация: 13.03.2018

Сообщений: 14

22.03.2018, 13:01

 [ТС]

3

Сделать так чтобы значение имеющее более 255 символов выводилось в таблицу. Т.е. чтобы не было ошибки вроде этой:
«Ошибка при вызове метода контекста (Execute): Произошла исключительная ситуация (Microsoft Word): Слишком длинный строковый параметр.»

0

Тест

Эксперт 1С

383 / 162 / 56

Регистрация: 26.02.2010

Сообщений: 1,241

22.03.2018, 13:03

4

Ну если ворд не может вместить себя больше, то это ворд перепрогарммировать нужно? Либо обрезать на 255 символов. Либо делать 2 переменные в ворде, и в 1с разбивать на 25 символов, если он больше. а в ворде соединять эти переменные

0

Эксперт 1С

3051 / 1998 / 524

Регистрация: 25.06.2009

Сообщений: 6,964

22.03.2018, 13:48

5

Ozam, попробуйте не через замену текста в шаблоне Word, а через создание переменных:
1. В шаблоне ворда меню Вставка — Экспресс-блоки — Поле — DocVariables — Задаем имя. Включаем/отключаем отображение переменных по Alt+F9
2. В 1С задаем значение переменной как: MSWord.Variables(«Data»).Value = …

По опыту работы с шаблонами: если можно работать с переменными в шаблоне, а не с заменой текста — лучше так и делать.

1

0 / 0 / 0

Регистрация: 13.03.2018

Сообщений: 14

23.03.2018, 09:30

 [ТС]

6

Вы можете показать какой-нибудь пример?

0

_ЕГОР_

Тест

Эксперт 1С

383 / 162 / 56

Регистрация: 26.02.2010

Сообщений: 1,241

23.03.2018, 09:32

7

Так вот же пример

1C
1
MSWord.Variables("Data").Value = ...

0

I recognize that this is a year old but since the technical side of the question never got answered I figured I take the time to post this for who ever stumbles upon it.

You could do something like this of you really must do it this way.

FindAndReplace(word, replacementKey, SequentialReplaceToken);
var restOfText = replaceWithText;
while (restOfText.Length > 20)
{
    var firstTwentyChars = restOfText.Substring(0, 20);
    firstTwentyChars += SequentialReplaceToken;
    restOfText = restOfText.Substring(20);
    FindAndReplace(word, SequentialReplaceToken, firstTwentyChars);
}
FindAndReplace(word, SequentialReplaceToken, restOfText);

FindAndReplace(…) being a wrapper over the Word interop Function.
Like so:

private void FindAndReplace(Application doc, object findText, object replaceWithText)
{
    //options
    object matchCase = false;
    object matchWholeWord = true;
    object matchWildCards = false;
    object matchSoundsLike = false;
    object matchAllWordForms = false;
    object forward = true;
    object format = false;
    object matchKashida = false;
    object matchDiacritics = false;
    object matchAlefHamza = false;
    object matchControl = false;
    object read_only = false;
    object visible = true;
    object replace = 2;
    object wrap = 1;
    //clear previous formatting
    doc.Selection.Find.ClearFormatting();
    //execute find and replace
    doc.Selection.Find.Execute(ref findText, ref matchCase, ref matchWholeWord,
        ref matchWildCards, ref matchSoundsLike, ref matchAllWordForms, ref forward, ref wrap, ref format, ref replaceWithText, ref replace,
        ref matchKashida, ref matchDiacritics, ref matchAlefHamza, ref matchControl);
}

And SequentialReplaceToken being a string constant that is known to never come up in the document.

I recognize that this is a year old but since the technical side of the question never got answered I figured I take the time to post this for who ever stumbles upon it.

You could do something like this of you really must do it this way.

FindAndReplace(word, replacementKey, SequentialReplaceToken);
var restOfText = replaceWithText;
while (restOfText.Length > 20)
{
    var firstTwentyChars = restOfText.Substring(0, 20);
    firstTwentyChars += SequentialReplaceToken;
    restOfText = restOfText.Substring(20);
    FindAndReplace(word, SequentialReplaceToken, firstTwentyChars);
}
FindAndReplace(word, SequentialReplaceToken, restOfText);

FindAndReplace(…) being a wrapper over the Word interop Function.
Like so:

private void FindAndReplace(Application doc, object findText, object replaceWithText)
{
    //options
    object matchCase = false;
    object matchWholeWord = true;
    object matchWildCards = false;
    object matchSoundsLike = false;
    object matchAllWordForms = false;
    object forward = true;
    object format = false;
    object matchKashida = false;
    object matchDiacritics = false;
    object matchAlefHamza = false;
    object matchControl = false;
    object read_only = false;
    object visible = true;
    object replace = 2;
    object wrap = 1;
    //clear previous formatting
    doc.Selection.Find.ClearFormatting();
    //execute find and replace
    doc.Selection.Find.Execute(ref findText, ref matchCase, ref matchWholeWord,
        ref matchWildCards, ref matchSoundsLike, ref matchAllWordForms, ref forward, ref wrap, ref format, ref replaceWithText, ref replace,
        ref matchKashida, ref matchDiacritics, ref matchAlefHamza, ref matchControl);
}

And SequentialReplaceToken being a string constant that is known to never come up in the document.

Сидел я крутил какие-то документы с макросами и обычный, вполне работающий макрос выпал с ошибкой:

Run-time error ‘5854’:
Слишком длинный строковый параметр

Вот срань, оказывается свойство объекта FindReplace .Find.Replacement.Text в VBA не может принимать параметры длиной больше 255 символов (привет, 70-е). А в автозаменах довольно легко упереться в эту крохотную границу. Странно, но параметр .Execute ReplaceWith: «replacementText» имеет точно такое ограничение.

Вот кусок кода, который вылетал с ошибкой, потому что citeEn (наша переменная с текстом) был слишком длинным.

With .Content.Find
   .Text = "#CitationPlaceholder#"
   .Replacement.Text = citeEn 'не больше 255 символов
   .Execute Replace:=wdReplaceAll
End With

Гугл рекомендовал мне рекурсивно разбивать .Replacement.Text на куски по 250 символов и автозаменять друг за другом. Однако громоздкость этого решения меня напугала, поэтому я подумал что лучше бы мне искать текст, выделять его, и заменять выделенное на наш большой текст:

Selection.Find.ClearFormatting
Selection.Find.Execute FindText:="#CitationPlaceholder#", Wrap:=wdFindContinue
If Selection.Find.Found = True Then Selection.Text = citeEn 'много символов

Такой способ позволяет заменить как минимум 900 знаков, а дальше я не проверял.

Ярлыки: MS Word macro, VBA


Ближайшие сообщения

Похожие сообщения

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

С этим вы обычной можете столкнуться при создании шаблона, для экспорта данных из эксель в ворд, при замене текста, дополнительно я покажу как исправить еще одну ошибку.

Давайте возьмём пример из первого видео, перейдете по ссылке в описании на странице есть файл в архиве.

Давайте сделаем так что у нас в заголовке таблицы будет не адрес, а текст для примера. Будем практиковаться на основе ячейки C2.

Давайте сделаем проверку длинны текста в ячейке, используя функцию ДЛСТР — длина строки. У нас здесь сейчас находится 15 символов.

Сделаем больше текста для этого я в Microsoft Word используя функцию LOREM(), которая сформирует случайный текст.

Теперь я скопирую текст, нужен будет блокнот, вставлю текст из буфера обмена, уберу лишние отступы переносы.

Давайте посмотрим какой длины у нас получится сейчас этот текст. Так вот у нас даже не помещается текст на экране, поправим таблицу. Длина текста в ячейке 598 символов с пробелами.

Давайте перейдём в Редактор Visual Basic, alt+f11 и посмотрим код прошлого примера.

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

Теперь откроем шаблон и заменим Адрес на Текст и исправим конструкцию для замены на &text.

Сохраним, закроем все лишнее, совместим для наглядности эксель файл и папку для вывода ворд файлов.

Посмотрим, что теперь получится, изменю масштаб, для доступа к кнопке запуска макроса.

Появляется ошибка № 5854 — слишком длинный строковый параметр.

И хотя бланк сформировался, произошло не то что ожидалось, ID вывели, серийный номер не изменился, потому как по коду данного макроса, мы не дошли до номера мы остановились вот здесь, ошибка произошла выше.

Давайте откроем диспетчер задач, существует проблема которую мы сейчас решим, иначе у нас при любой ошибке в работе макроса в Диспетчере задач в фоне остается запущен экземпляр Microsoft Word в котором рухнул наш шаблон.

Давайте ещё раз попробуем сформировать посмотрим, что у изменится.

Опять ошибка, и сейчас в Диспетчере задач повис Microsoft Word, его нужно закрыть и так придется делать постоянно, будем снимать задачу иначе будут появляться новые ошибки.

Давайте теперь сделаем выход из нашей функции, где мои работаем, здесь у нас создание файла проходит нормально, этот кусок у нас нормально отрабатывает.

Вставим вот здесь следующий код:

On Error GoTo ErrorHadler

Это у нас метка перехода, если произойдет ошибка, мы перейдём в конец модуля, вот здесь мы сделаем Exit Sub — Выход из модуля.

Ниже напишем ErrorHandler: наша метка и здесь нам нужно будет вставить код сохранения, закрытия и выхода из Word.

wdDoc.Save
wdDoc.Close
wdApp.Quit

Также добавим сообщение

MsgBox "Не выполнено! " + Error

Вот теперь мы избавимся проблемы, когда у нас будет зависать в Диспетчере задач Microsoft Word, который мы не успеваем закрыть.

Давайте выполним макрос, появится сообщение — не выполнено слишком длинный строковый параметр, в принципе у нас документ сформировался, но он в целом не полностью отработал.

Сейчас мы исправим эту проблему, кстати гляну в диспетчер задач у нас Microsoft Word нигде не висит, и он нам не мешает. OK.

Теперь снова перейдём в редактор VBA. и разобьем переменную Text$ на фрагменты допустимой длины.

Ну кроме исправлю маленькую опечатку, тут естественно должен быть &text.

Дайте я посмотрю, что изменится, хотя даже если мы исправили это значение, всё равно ничего не получилось.

Теперь удалим снова бланк, вернемся вот сюда, зададим переменную temp равно Left возьмём от переменной Text$ 255 символов, снова создадим переменную temp2, воспользуемся теперь функцией Mid, мы возьмём начиная с 256 символа текст длиной 255 символов.

Теперь нужно будет продублировать здесь строку для замены значений, укажем переменные temp, temp2, здесь мы сделаем заменяемое значение text2.

Сделаем с запасом, ещё разок скопирую и вставлю

temp3 = Mid(Text$, 512, 255).

Теперь мы шагнем от 256 + 255 равно 511, начиная с 512 символа мы опять шагнем на 255 символов.

Ещё продублирую строку замены, переменная temp3, значение text3.

Как нам указать в шаблоне заменяемые значения? А мы их ведем просто в наш шаблон, уже есть вот эта строка &text, мы её скопируем и вставим несколько раз, дописав числа 2 и 3.

То есть у нас всякий раз вот этот фрагмент текст будет заменяться на значения из наших переменных temp, temp2, temp3. Можно в коде VBA продолжать добавлять разбивку основного текста на части, но будьте внимательны, указывая смещение и длину символов. Соответствующе правки так же вносите в шаблон.

Давайте попробуем запустить и посмотрим, что получится, закрыли, свернули.

Впишемся ли мы в данное ограничение, О’кей, готово.

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

Следующие файлы так же сформировались, но тут у нас все осталось как обычно.

Вот таким простым способом вы можете обойти эту условность, ограничение в 255 символов, в принципе сама строковая переменная Text$ может очень много вместить в себя значений, но при работе вот этой функции FindText замена текста, вот здесь, мы не можем производить большие какие-то преобразования, но вот с такой разбивкой большого текста на переменные в принципе можно это продолжать дальше.

То есть у нас 512 + 255 получается 767, следующий шаг в 255 символов можно делать с 768 знака.

У нас же есть ещё место и дальше можно продолжать опять там делать дальше разбивку, если у вас будет очень большой текст.

Исходный код из видео

Sub main()
Dim wdApp As Object
Dim wdDoc As Object

HomeDir$ = ThisWorkbook.Path
Set wdApp = CreateObject("Word.Application")
i% = 2
Do
If Cells(i%, 1).Value = "" Then Exit Do
If Cells(i%, 1).Value <> "" Then

NPP$ = Cells(i%, 1).Text
ID$ = Cells(i%, 2).Text
Text$ = Cells(i%, 3).Text
SN$ = Cells(i%, 4).Text

DataC$ = Date

FileCopy HomeDir$ + "template.doc", HomeDir$ + "" + NPP$ + "_" + ID$ + "_" + DataC$ + ".doc"
Set wdDoc = wdApp.Documents.Open(HomeDir$ + "" + NPP$ + "_" + ID$ + "_" + DataC$ + ".doc")

On Error GoTo ErrorHandler

temp = Left(Text$, 255)
temp2 = Mid(Text$, 256, 255)
temp3 = Mid(Text$, 512, 255)
temp4 = Mid(Text$, 768, 255)

wdDoc.Range.Find.Execute FindText:="&date", ReplaceWith:=DataC$
wdDoc.Range.Find.Execute FindText:="&id", ReplaceWith:=ID$
wdDoc.Range.Find.Execute FindText:="&text", ReplaceWith:=temp
wdDoc.Range.Find.Execute FindText:="&text2", ReplaceWith:=temp2
wdDoc.Range.Find.Execute FindText:="&text3", ReplaceWith:=temp3
wdDoc.Range.Find.Execute FindText:="&text4", ReplaceWith:=temp4

wdDoc.Range.Find.Execute FindText:="&sn", ReplaceWith:=SN$
wdDoc.Save
wdDoc.Close
End If

i% = i% + 1
Loop
wdApp.Quit
MsgBox "Готово!"

Exit Sub

ErrorHandler:

wdDoc.Save
wdDoc.Close
wdApp.Quit

MsgBox "Не выполнено! " + Error
End Sub

Исходный код из видео — скачать архив с файлами


ZIP архив с файлами


Смотрите видео: Исправляем ошибку VBA № 5854 слишком длинный строковый параметр в шаблоне word из таблицы excel 255 символов

Понравилась статья? Поделитесь ею с друзьями и напишите отзыв в комментариях!

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

Вы могли бы сделать что-то подобное, вы действительно должны сделать это таким образом.

FindAndReplace(word, replacementKey, SequentialReplaceToken);
var restOfText = replaceWithText;
while (restOfText.Length > 20)
{
    var firstTwentyChars = restOfText.Substring(0, 20);
    firstTwentyChars += SequentialReplaceToken;
    restOfText = restOfText.Substring(20);
    FindAndReplace(word, SequentialReplaceToken, firstTwentyChars);
}
FindAndReplace(word, SequentialReplaceToken, restOfText);

FindAndReplace (…) является оболочкой над функцией взаимодействия Word.
Например:

private void FindAndReplace(Application doc, object findText, object replaceWithText)
{
    //options
    object matchCase = false;
    object matchWholeWord = true;
    object matchWildCards = false;
    object matchSoundsLike = false;
    object matchAllWordForms = false;
    object forward = true;
    object format = false;
    object matchKashida = false;
    object matchDiacritics = false;
    object matchAlefHamza = false;
    object matchControl = false;
    object read_only = false;
    object visible = true;
    object replace = 2;
    object wrap = 1;
    //clear previous formatting
    doc.Selection.Find.ClearFormatting();
    //execute find and replace
    doc.Selection.Find.Execute(ref findText, ref matchCase, ref matchWholeWord,
        ref matchWildCards, ref matchSoundsLike, ref matchAllWordForms, ref forward, ref wrap, ref format, ref replaceWithText, ref replace,
        ref matchKashida, ref matchDiacritics, ref matchAlefHamza, ref matchControl);
}

И SequentialReplaceToken является строковой константой, которая, как известно, никогда не появляется в документе.

Трудовой договор

Для большенства организаций стандартная печатная форма трудового договора в программе 1С:Зарплата и управление персоналом не подходит. Фирма 1С, в восьмой версии своей программы, любезно предусмотрела возможность добавлять дополнительные печатные формы для документов и других объектов. Воспользуемся данной возможностью и создадим трудовой договор, который будет открываться в Microsoft Word.

Специалисты по конфигурированию могут разрабатывать внешние обработки вне конфигурации, используемой в организации. Разработанный отчет или обработка передается в виде файла так называемой внешней обработки с расширением .epf. Пользователь может подключить эту обработку к конфигурации самостоятельно.

Сведения о подключенных обработках хранятся в справочнике «Внешние обработки». Чтобы подключить новую внешнюю обработку, нужно зарегистрировать ее в указанном справочнике.

Технические требования к внешней печатной форме

Внешняя обработка должна содержать:

  • Реквизит «СсылкаНаОбъект», куда при вызове будет передана ссылка на объект, для которого необходимо выполнить печать;
  • Необязательный реквизит «ДополнительныеПараметры» произвольного типа, которому будут передаваться дополнительные параметры примитивного типа в виде структуры;
  • Функция Печать() — без параметров,  возвращающая табличный документ;
  • Также внешняя печатная обработка может иметь в своем составе макет «Параметры_Авторегистрации», используемый для автоматического заполнения принадлежности печатной формы в справочнике «Внешние обработки» и состоящий из двух колонок: «Полное имя метаданного» и «Имя табличной части».

Создание внешней обработки

Запустим 1С:Предприятие в режиме «Конфигуратор» и через меню «Файл» — «Новый» создадим внешнюю обработку.

Создание внешней обработки

Создадим реквизит «СсылкаНаОбъект». Для этого нажимем кнопку «Добавить» или клавишу «Insert» и заполним свойства. В зависимости от того, для каких объектов будет использоваться эта печатная форма, нужно выбрать тип. В нашем случае, внешняя печатная форма будет использоваться только для справочника «Сотрудники организации», поэтому укажем соответствующий тип «СправочникСсылка.СотрудникиОрганизаций».

Свойства реквизита

Реквизит «ДополнительныеПараметры» нам не понадобится. Создадим экспортную функцию Печать() («Действия» — «Открыть модуль объекта»).

 Функция Печать()

Прежде чем написать тело этой функции, создадим макет, который она будет возвращать.

Макет трудового договора в формате Microsoft Word

Существует, по меньшей мере, три способа создания шаблона.

Первый. В тексте документа содаются метки особого формата, например, «м_НомерДоговора», затем, в модуле обработки производится поиск и замена значений.

Второй способ. В документе Word создаются закладки, к которым потом можно обращаться по имени. Минус этого способа в том, что метка должна быть уникальна, т.е., например, если нужно вставить фамилию сотрудника в каждый абзац текста, то придется сделать несколько закладок с разными именами.

Способ три. В шаблон добавляются служебные поля, например, «DocVariable» или «Author». Используя DocVariable можно обращаться к переменной по имени, например, «ДокументВорд.Variables.Add(ИмяПеременной, ЗначениеПеременной);», но ее не видно в шаблоне. Поле «Author» отображается в шаблоне, но обращаться к нему придется в цикле по индексу: «ДокументВорд.Fields.item(Индекс).Result.Text = Значение;».

На мой взгляд, первый способ является самым оптимальным. Шаблон документа легко редактируется, метки видны в тексте, для создания меток не нужны сложные вставки. Поэтому будем делать шаблон именно этим способом.

Откроем программу Microsoft Office. Для примера добавим лишь одну строку: «Трудовой договор № [НомерДоговора]».

Сохраним шаблон.

Добавим получившийся шаблон в нашу обаботку. Для этого выбираем «Макеты» и нажимаем кнопку «Добавить» или клавишу «Insert».

Выбор макета трудового договора

Откроется конструктор запроса, в котором выберем тип «Active Document» и файл шаблона.

Конструктор макета Active Document

Функция Печать()

Вернемся к функции, которую мы создали ранее. Настало время написать ее тело.

// Предопределенная функция для внешних печатных форм
//
Функция Печать() Экспорт// Получим объект Microsoft Word из макета
   
ОбъектВорд = ПолучитьМакет(«ТрудовойДоговор»).Получить();// Получим документ из объекта и активируем его
   
Документ = ОбъектВорд.Application.Documents(1);
   
Документ.Activate();// Поиск и замена маркеров
   
Замена = Документ.Content.Find;
   
Замена.Execute(«[НомерДоговора]», , , , , , , , , «007», 2);// Вывод документа
   
ОбъектВорд.Application.Visible = Истина;
   
ОбъектВорд.Activate();

КонецФункции

// Печать()

Из кода видно, что в файле шаблона производится поиск строки «[НомерДоговора]» и ее замена на строку «007».

Параметры авторегистрации

Для автоматического заполнения принадлежности печатной формы к объектам конфигурации, добавим еще один макет «Параметры_Авторегистрации». Это будет табличный документ, содержащий одну колонку с именами объектов метаданных, к которым будет принадлежать печатная форма. В нашем случае таблица будет выглядить следующим образом.

Параметры авторегистрации

Сохраним получившуюся внешнюю обработку.

Подключение дополнительных внешних печатных форм

Запустим 1С Предприятие. Откроем справочник «Дополнительные внешние печатные формы» через меню «Сервис» — «Дополнительные отчеты и обработки».

Нажмем кнопку «Добавить», затем зарегистрируем новую печатную форму, нажав «Заменить файл внешней обработки». Автоматически заполнится принадлежность печатной формы справочнику «Сотрудники». Выберем «Трудовой договор» в колонке «Заменяемая печатная форма» чтобы стандартная печатная форма более не использовалась.

Регистрация внешней печатной формы

В итоге справочник будет выглядить следующим образом.

Дополнительные внешние печатные формы

Проверка результата

Откроем любого работающего сотрудника и нажмем кнопку «Печать» — «Трудовой договор». Откроется документ Microsoft Word с трудовым договором под номером «007».

Трудовой договор в MS Word

Дальнейшее описывать не имет смысла. Думаю, не составит большого труда доработать функцию Печать() и макет договора.

  • Ошибка при вызове метода контекста execute произошла исключительная ситуация 0x80020005
  • Ошибка при вызове метода контекста createobject
  • Ошибка при вызове метода контекста connectagent
  • Ошибка при вызове метода контекста connect произошла исключительная ситуация v83 comconnector 1
  • Ошибка при вызове метода контекста connect неизвестная ошибка v83 application