Форум программистов, компьютерный форум, киберфорум
MS Office Word
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.59/88: Рейтинг темы: голосов - 88, средняя оценка - 4.59
 Аватар для Ируся
3 / 3 / 0
Регистрация: 24.07.2015
Сообщений: 79

При слиянии в word из excel сохранить в отдельный файл с названиями по определенному полю

19.04.2022, 12:45. Показов 27314. Ответов 48

Студворк — интернет-сервис помощи студентам
Добрый день!
Есть файл word подготовленный по методу слияния и состоящий из 2000 страниц. Или сделать сразу из файла слияния такое сохранение.
Нужно сохранить каждую станицу в отдельный файл каждый под своим именем (наименование организации) которое состоит в вверху страницы и может содержать буквы и/или цифры и/или кавычки.
Помогите, пожалуйста, с макросом.
Спасибо.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
19.04.2022, 12:45
Ответы с готовыми решениями:

Привязать файл Word к определенному полю в базе данных
Вопрос вот в чем. Есть база данных Access в ней есть поле книга, мне надо сделать, чтобы каждой книге принадлежал файл word либо pdf, для...

Excel и Word: при слиянии из таблицы дата отображается не корректно
Добрый день. При слиянии из таблицы дата отображается не корректно..... Месяц, день, год. как это исправить. форматы менять пробовал-...

Как сохранить листы Excel в отдельный файл
Здравствуйте Уважаемые! Помогите решить задачу!!! Есть книга Excel с несколькими листами. Как реализовать сохранение каждого листа...

48
малоболт
1328 / 510 / 213
Регистрация: 30.01.2020
Сообщений: 1,244
19.04.2022, 21:05
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Ируся Посмотреть сообщение
а как быть с повторяющимися наименованиями?
Тут уж хорошо бы вам проанализировать и решить - ЧТО ВАМ нужно с ними делать и в каких случаях?
Могу пока просто предложить стандартный финт ушами от Windows - добавлять номер в скобках в конце названия таких файлов:
Вставить между 59 и 60 строкой это:
Visual Basic
60
61
62
63
64
65
66
67
68
      
      if FSO.FileExists( FSO.BuildPath (wDir, fName &".docx")) then
        for ii=1 to 99 step 1
          if not FSO.FileExists(FSO.BuildPath (wDir, fName & " ("& ii &").docx")) then
            fName = fName & " ("& ii &")"
            exit for
          end if
        next
      end if
Цитата Сообщение от Ируся Посмотреть сообщение
там может быть и 5 строк с новыми суммами и 15 и соответственно все они в разных документах
А должны быть в одном? И вы ни словом об этом в ТЗ?
Что сказать? Кроме вас никто не знает требуемой логики. Если вы не расскажете что вам хотелось бы делать с этими повторяшками (насколько возможно подробнее и с приложением файлов примеров), то мы об этом так и не узнаем и вряд ли что-то предложим.
0
Модератор
Эксперт MS Access
 Аватар для shanemac51
12511 / 5085 / 814
Регистрация: 07.08.2010
Сообщений: 14,959
Записей в блоге: 4
19.04.2022, 21:22
Ируся,
я обычно помещаю код в ексель -книгу
-короче код
- легче отлаживать
Visual Basic
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
58
59
60
61
Option Explicit
 
Dim wrd, aa, aColNums
Dim spath, sname, irow, icol, srow, zrow, ii, ns, nn
Dim xm(66) As String 'массив того, что искать в word-шаблоне, с запасом
Dim ym(66) As Long 'массив номеров колонок Escel-файла для замены
 
Sub m220419word()
spath = Excel.ActiveWorkbook.Path & "\"
 
Set wrd = CreateObject("Word.Application")
wrd.Visible = False ''True
'лучше потом поменять на false, чтобы Word  открывался невидимым
 
With Excel.ActiveWorkbook.Worksheets(1) '''''''''''''
aa = .UsedRange.Value
End With
 
ns = 0
Dim r1, r1k, c1, c1k
c1k = UBound(aa, 2)
c1 = LBound(aa, 2)
r1k = UBound(aa, 1)
r1 = LBound(aa, 1)
''6             1             10            10
 
For icol = c1 To c1k
srow = "@" & aa(1, icol)
If Len(srow) > 1 Then
Debug.Print icol, srow
ns = ns + 1: xm(ns) = srow: ym(ns) = icol
End If
'Число строк заголовков, которые пропускать
 
Next icol
Debug.Print ns, xm(1), ym(1)
''цикл по строкам
For irow = r1 + 1 To r1k
xlRow2Wrd
Next irow
 
wrd.Quit
'закроем Word
Set wrd = Nothing
'очистим объекты
''MsgBox "Я кончила! Твоя очередь."
Debug.Print Now
End Sub
 
Sub xlRow2Wrd()
With wrd.documents.Open(spath & "исх19.dotx")
For ii = 1 To ns
Debug.Print ii, ym(ii), xm(ii)
.Content.Find.Execute xm(ii), False, False, False, False, False, True, 1, False, aa(irow, ym(ii)), 2
Next
sname = aa(irow, 1)
sname = Replace(sname, """", "_")
.SaveAs2 spath & sname & ".docx", 12
.Close
End With
End Sub
1
 Аватар для Ируся
3 / 3 / 0
Регистрация: 24.07.2015
Сообщений: 79
19.04.2022, 21:49  [ТС]
Цитата Сообщение от Punkt5 Посмотреть сообщение
Если вы не расскажете что вам хотелось бы делать с этими повторяшками (насколько возможно подробнее и с приложением файлов примеров), то мы об этом так и не узнаем и вряд ли что-то предложим.
Спасибо, с добавлением номера в скобках помогло.


Punkt5,
по поводу того что могут быть услуги у одной компании больше одной, забыла.
нужно чтобы было так:
Если столбец "клиент" и "номер договора" совпадает со следующей строкой то оставалось одним, а столбцы "Услуга", "Цена за 1 ед. (новая)", "Сумма (новая)" шли под предыдущими такими же. Во вложении ексель файл и ворд как я это вижу. Выделила и оставила примечания в файле.
Но если название одно, а номера договоров разное чтобы шло как дубль и в скобка было (1) (2) и тд. На сколько это реалистично?
Спасибо.
Вложения
Тип файла: docx ООО РЮМАШКА.docx (18.9 Кб, 17 просмотров)
Тип файла: xlsx увелич.xlsx (10.8 Кб, 14 просмотров)
0
 Аватар для Ируся
3 / 3 / 0
Регистрация: 24.07.2015
Сообщений: 79
19.04.2022, 21:50  [ТС]
Цитата Сообщение от shanemac51 Посмотреть сообщение
я обычно помещаю код в ексель -книгу
-короче код
- легче отлаживать
в книгу это как? я только начала погружаться в это...
0
 Аватар для Ируся
3 / 3 / 0
Регистрация: 24.07.2015
Сообщений: 79
19.04.2022, 22:32  [ТС]
Цитата Сообщение от shanemac51 Посмотреть сообщение
Visual Basic
попробовала ваш скрипт и ошибка сразу
Миниатюры
При слиянии в word из excel сохранить в отдельный файл с названиями по определенному полю  
0
Модератор
Эксперт MS Access
 Аватар для shanemac51
12511 / 5085 / 814
Регистрация: 07.08.2010
Сообщений: 14,959
Записей в блоге: 4
20.04.2022, 06:18
Цитата Сообщение от Ируся Посмотреть сообщение
попробовала ваш скрипт и ошибка сразу
это не скрипт - это код в книге екселя с данными и поддержкой макросов
но конечно проверю сегодня, может в самом деле ошиблась
0
 Аватар для Ируся
3 / 3 / 0
Регистрация: 24.07.2015
Сообщений: 79
20.04.2022, 09:43  [ТС]
shanemac51, его надо применить в Excel? Как его внедрить в него? Я просто не когда не сталкивалась с этим.
Если подскажите, буду счастлива. Я просто пробовала его по схеме выше. Сохранила шаблон, код, и ворд файл в одном месте и нажала на этот файл с кодом. И сразу ошибка. Как его открыть, не совсем тогда понимаю.

Добавлено через 1 час 44 минуты
Punkt5, а можно в ваш код добавить код shanemac51 чтобы что-то дельное вышло?
0
Модератор
Эксперт MS Access
 Аватар для shanemac51
12511 / 5085 / 814
Регистрация: 07.08.2010
Сообщений: 14,959
Записей в блоге: 4
20.04.2022, 09:57
Цитата Сообщение от Ируся Посмотреть сообщение
там может быть и 5 строк с новыми суммами и 15 и соответственно все они в разных документах
кодом можно и это сделать, чтобы любое количество строк одного клиента шло в один отчет, но это уже конкретика реальной задачи - чтобы решить задачу надо видеть реальные исходные данные( можно заменить фамилию или название клиента на условные данные, но смысл строк должен сохраниться)

например есть
- сначала все строки на газ
- затем на воду
- затем на вывоз мусору

надо же выбрать данные Иванова
- газ
- вода
- мусор

затем Петрова( у него нет газа)
- вода
- мусор

....
0
 Аватар для Ируся
3 / 3 / 0
Регистрация: 24.07.2015
Сообщений: 79
20.04.2022, 10:52  [ТС]
Цитата Сообщение от shanemac51 Посмотреть сообщение
видеть реальные исходные данные
могу сделать так, указала часть услуг которые встречаются по всей таблице, точнее с чего начинается название услуги и дальше есть текст, поиск по части строки, можно прописать?
Вложения
Тип файла: xlsx увелич.xlsx (12.3 Кб, 10 просмотров)
0
 Аватар для Ируся
3 / 3 / 0
Регистрация: 24.07.2015
Сообщений: 79
20.04.2022, 11:44  [ТС]
Punkt5, у меня почему-то берет название из колонки с названием, а не из первого столбца, как быть?
QBasic/QuickBASIC
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
DIM xls, wrd, FSO, Sha, xDir, wDir, sDir, xF, sFiles, xFiles, aa, aWhatFind, aColNums
  CONST hdrRows=1 'Число строк заголовков, которые пропускать
  aWhatFind=Array("@Клиент","@Договор", "@Услуга", "@Цена за 1 ед. (новая)", "@Сумма (новая)", "@Комментарий") 'массив того, что искать в word-шаблоне
  aColNums =Array(2,3,5,10,11,13) 'массив номеров колонок Escel-файла для замены
  Set FSO = CreateObject("Scripting.FileSystemObject") 
  
  xDir = FSO.GetAbsolutePathname("") ' xlsx ищем в текущей папке
  sDir = xDir 'папка, где лежат шаблоны, пока пишем текущую папку 
  wDir = xDir 'папка, куда кладём готовый результат. пока в текущую
  with  CreateObject("Shell.Application")
    Set sFiles = .NameSpace(sDir).Items() 'всё что есть в папке шаблонов
    Set xFiles = .NameSpace(xDir).Items() 'пока то же
  END with
  sFiles.Filter 64, "*.dotx" 'смотрим в папке шаблонов на файлы с такой маской.
  IF sFiles.Count < 1 THEN 'ФАЙЛОВ НЕТ
    wsh.echo "Нет шаблонов В папке " & wDir
    wsh.quit
  END IF
  xFiles.Filter 64, "*.xlsx" 'смотрим в папке xlsx только на файлы с такой маской.
  IF xFiles.Count < 1 THEN 'ФАЙЛОВ НЕТ
    wsh.echo "Нет файлов *.xlsx В папке " & xDir
    wsh.quit
  END IF
 
  Set xls = CreateObject("Excel.Application")
  xls.Visible = True 'лучше потом поменять на false, чтобы Excel открывался невидимым
  Set wrd = CreateObject("Word.Application")
  wrd.Visible = True 'лучше потом поменять на false, чтобы Word  открывался невидимым
 
  FOR each xF in xFiles 'переберём все xlsx файлы
    With xls.WorkBooks.OPEN(xf.Path)
      aa = .Sheets(1).UsedRange.Value
      .CLOSE
    END with
    FOR iRow = HdrRows+1 TO UBOUND(aa) STEP 1
      xlRow2Wrd() ' обработаем каждую строку
    NEXT
  NEXT
  xls.quit 'закроем Excel
  wrd.quit 'закроем Word
  Set wrd=Nothing: Set xls=Nothing: Set FSO=Nothing: Set Sha=Nothing
  Set sFiles=Nothing: Set xFiles=Nothing: Set xF=Nothing 'очистим объекты
  wsh.echo "Я кончила! Твоя очередь." 
  wsh.quit
  
  SUB xlRow2Wrd()
  DIM fName
  CONST Repl=""".,&@#№'<>"
  FOR each sF in sFiles
    with wrd.documents.OPEN(sF.Path)
      FOR ii = 0 TO UBOUND(aColNums) STEP 1
        IF aColNums(ii) <= UBOUND(aa,2) THEN
          .Content.Find.Execute aWhatFind(ii), False, False, False, False, False, True, 1, False, aa(iRow,aColNums(ii)), 2
        END IF
      NEXT
      fName = aa(iRow,aColNums(0))
      FOR ii=1 TO LEN(Repl) STEP 1
        fName = replace(fName,Mid(repl,ii,1),"")
      NEXT
 IF FSO.FileExists( FSO.BuildPath (wDir, fName &".docx")) THEN
        FOR ii=1 TO 99 STEP 1
          IF NOT FSO.FileExists(FSO.BuildPath (wDir, fName & " ("& ii &").docx")) THEN
            fName = fName & " ("& ii &")"
            EXIT FOR
          END IF
        NEXT
      END IF
      .SaveAs FSO.BuildPath (wDir, fName),12 
      .CLOSE
    END with
  NEXT
END SUB
0
малоболт
1328 / 510 / 213
Регистрация: 30.01.2020
Сообщений: 1,244
20.04.2022, 14:39
Цитата Сообщение от Ируся Посмотреть сообщение
у меня почему-то берет название из колонки с названием, а не из первого столбца, как быть?
В 56 строке вместо aColNums(0) напишите 1 (номер нужной колонки)
Visual Basic
56
fName = aa(iRow,1)
2
0 / 0 / 0
Регистрация: 01.05.2022
Сообщений: 7
02.05.2022, 00:57
Punkt5, большое Вам спасибо за код. Я его также использую для аналогичной ситуации.
Но у меня возникла ошибка при исполнении кода. Дело в том, что в таблице присутствуют большие тексты (примерно 105 слов в ячейке), и скрипт отказывается работать, выдает следующую ошибку: "Слишком длинный строковый параметр". Фото ошибки приложено к посту. Можно как-то обойти эту ошибку?

Visual Basic
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
58
59
60
61
62
63
64
dim xls, wrd, FSO, Sha, xDir, wDir, sDir, xF, sFiles, xFiles, aa, aWhatFind, aColNums
  Const hdrRows=2 'Число строк заголовков, которые пропускать
  aWhatFind=Array("Имя файла","@Дата ENG","@Дата RUS","«Компания_ENG»","«Компания_RUS»","«Президент_ENG»","«Президент_RUS»","«ИПфизик_ENG»","«ИПфизик_RUS»","«ФИО_ENG»","«ФИО_RUS»","«Номер_и_дата_договора_ENG»","«Номер_и_дата_договора_RUS»","«Обязанности_ENG»","«Обязанности_RUS»","«Период_ENG»","«Период_RUS»","«Сумма_ENG»","«Сумма_RUS»") 'массив того, что искать в word-шаблоне
  aColNums =Array(1,12,13,7,6,8,9,5,4,2,3,14,15,11,10,16,17,18,19) 'массив номеров колонок Escel-файла для замены
  Set FSO = CreateObject("Scripting.FileSystemObject") 
  
  xDir = FSO.GetAbsolutePathname("") ' xlsx ищем в текущей папке
  sDir = xDir 'папка, где лежат шаблоны, пока пишем текущую папку 
  wDir = xDir 'папка, куда кладём готовый результат. пока в текущую
  with  CreateObject("Shell.Application")
    Set sFiles = .NameSpace(sDir).Items() 'всё что есть в папке шаблонов
    Set xFiles = .NameSpace(xDir).Items() 'пока то же
  end with
  sFiles.Filter 64, "*.dotx" 'смотрим в папке шаблонов на файлы с такой маской.
  if sFiles.Count < 1 Then 'ФАЙЛОВ НЕТ
    wsh.echo "Нет шаблонов В папке " & wDir
    wsh.quit
  end if
  xFiles.Filter 64, "*.xlsx" 'смотрим в папке xlsx только на файлы с такой маской.
  if xFiles.Count < 1 Then 'ФАЙЛОВ НЕТ
    wsh.echo "Нет файлов *.xlsx В папке " & xDir
    wsh.quit
  end if
 
  Set xls = CreateObject("Excel.Application")
  xls.Visible = True 'лучше потом поменять на false, чтобы Excel открывался невидимым
  Set wrd = CreateObject("Word.Application")
  wrd.Visible = True 'лучше потом поменять на false, чтобы Word  открывался невидимым
 
  for each xF in xFiles 'переберём все xlsx файлы
    With xls.WorkBooks.Open(xf.Path)
      aa = .Sheets(1).UsedRange.Value
      .Close
    end with
    for iRow = HdrRows+1 to uBound(aa) step 1
      xlRow2Wrd() ' обработаем каждую строку
    next
  next
  xls.quit 'закроем Excel
  wrd.quit 'закроем Word
  Set wrd=Nothing: Set xls=Nothing: Set FSO=Nothing: Set Sha=Nothing
  Set sFiles=Nothing: Set xFiles=Nothing: Set xF=Nothing 'очистим объекты
  wsh.echo "Я кончила! Твоя очередь." 
  wsh.quit
  
  Sub xlRow2Wrd()
  dim fName
  const Repl=""".,&@#№'<>"
  for each sF in sFiles
    with wrd.documents.Open(sF.Path)
      for ii = 0 to uBound(aColNums) step 1
        if aColNums(ii) <= uBound(aa,2) then
          .Content.Find.Execute aWhatFind(ii), False, False, False, False, False, True, 1, False, aa(iRow,aColNums(ii)), 2
        end if
      next
      fName = aa(iRow,aColNums(0))
      for ii=1 to Len(Repl) step 1
        fName = replace(fName,Mid(repl,ii,1),"")
      next
      .SaveAs FSO.BuildPath (wDir, fName),12 
      .Close
    end with
  next
end sub
Миниатюры
При слиянии в word из excel сохранить в отдельный файл с названиями по определенному полю  
0
малоболт
1328 / 510 / 213
Регистрация: 30.01.2020
Сообщений: 1,244
02.05.2022, 06:27
Smailm, FindAndReplace в Word ограничивает длину строки_которую_ищем и строки_на_которую_заменяем. Они не могут быть более 254 символов.
В Word-шаблоне длину строки_которую_ищем вы и сами надеюсь ограничите. А вот строку_на_которую_меняем придётся разбивать на небольшие_куски. И в цикле заменять строку_которую_ищем на этот небольшой_кусок+строка_которую_ищем. Пока не доберёмся до последнего куска, который заведомо меньше ограничения в 254 символа. И под конец на радостях меняем строку_которую_ищем на последний_кусок.
В вашем коде:
1. В первой строке в DIM добавьте wStr, xStr
2. 53-ю строку замените на:
Visual Basic
53
54
55
56
57
58
59
60
  wStr = aWhatFind(ii) 'то_что_ищем в word-шаблоне  = заведомо маленькое и заведомо НЕ ПОПАДАЮЩЕЕСЯ в том_на_что_меняем
  xStr = aa(iRow,aColNums(ii)) 'то_на_что_меняем (из excel-таблицы). Может быть велико
  While Len(xStr) > 250 'до тех пор пока то_на_что_меняем > 250 символов
    'меняем в цикле то_что_ищем на обрезок того_на_что_меняем + то_что_ищем на хвосте
    .Content.Find.Execute wStr, False, False, False, False, False, True, 1, False, left(xStr,250-len(wStr)) & wStr, 2 
    xStr = mid(xStr,251-len(wStr)) 'отрезаем то, что уже вставили от начала того_на_что_меняем
  loop
  .Content.Find.Execute wStr, False, False, False, False, False, True, 1, False, xStr, 2 'довставляем остаток
P.S. Код не отлаживал - просто набросал по логике. Могут быть мелкие описки. Но вроде постарался логику донести.
0
Модератор
Эксперт MS Access
 Аватар для shanemac51
12511 / 5085 / 814
Регистрация: 07.08.2010
Сообщений: 14,959
Записей в блоге: 4
02.05.2022, 11:08
Цитата Сообщение от Smailm Посмотреть сообщение
aWhatFind=Array("Имя файла","@Дата ENG","@Дата RUS","«Компания_ENG»","«Компания_RUS»"," «Президент_ENG»", "«Президент_RUS»","«ИПфизик_ENG»","«ИПфи зик_RUS»", "«ФИО_ENG»","«ФИО_RUS»","«Номер_и_дата_д оговора_ENG»", "«Номер_и_дата_договора_RUS»","«Обязанно сти_ENG»", "«Обязанности_RUS»","«Период_ENG»","«Пер иод_RUS»","«Сумма_ENG»","«Сумма_RUS»")
'массив того, что искать в word-шаблоне
 aColNums =Array(1,12,13,7,6,8,9,5,4,2,3,14,15,11, 10,16,17,18,19)
'массив номеров колонок Escel-файла для замены
предпочитаю иное описание замен, конечно столбцы описываю по-порядку

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
dim nc as long
dim aWhatFind(0 to 99) as String  ''с запасом + небольшое изменение в блоке замены
nc= 1         :aWhatFind(nc) = "Имя файла"
nc= 12        :aWhatFind(nc) = "@Дата ENG"
nc= 13        :aWhatFind(nc) = "@Дата RUS"
nc= 7         :aWhatFind(nc) = "«Компания_ENG»"
nc= 6         :aWhatFind(nc) = "«Компания_RUS»"
nc= 8         :aWhatFind(nc) = "«Президент_ENG»"
nc= 9         :aWhatFind(nc) = "«Президент_RUS»"
nc= 5         :aWhatFind(nc) = "«ИПфизик_ENG»"
nc= 4         :aWhatFind(nc) = "«ИПфизик_RUS»"
nc= 2         :aWhatFind(nc) = "«ФИО_ENG»"
nc= 3         :aWhatFind(nc) = "«ФИО_RUS»"
nc= 14        :aWhatFind(nc) = "«Номер_и_дата_договора_ENG»"
nc= 15        :aWhatFind(nc) = "«Номер_и_дата_договора_RUS»"
nc= 11        :aWhatFind(nc) = "«Обязанности_ENG»"
nc= 10        :aWhatFind(nc) = "«Обязанности_RUS»"
nc= 16        :aWhatFind(nc) = "«Период_ENG»"
nc= 17        :aWhatFind(nc) = "«Период_RUS»"
nc= 18        :aWhatFind(nc) = "«Сумма_ENG»"
nc= 19        :aWhatFind(nc) = "«Сумма_RUS»"
1
0 / 0 / 0
Регистрация: 01.05.2022
Сообщений: 7
02.05.2022, 12:19
Punkt5, благодарю Вас за оперативный ответ!

Ваш срипт работает блестяще, но к сожалению упирается в ограничение в 254 символа.

Длина проблемных строк, которые мы ищем, короткие ("«Обязанности_ENG»","«Обязанности_RUS»" ), они не превышают 254 символа.

Но вот содержимое этих ячеек для каждого человека может быть разным и у многих значительно превышает 254 символа. Причем обязанности каждого человека дублируется на английском и на русском языках. Например, 840 символов (Rus) + 840 символов (Eng) для одного человека.

Если я Вас правильно понял, то Вы предлагаете вручную дробить длинный текст на мелкие куски.
Учитывая, что людей будет много, то их двуязычных обязанностей тоже будет много. Получается, что вариант с ручным разделением текста не подойдет, это очень трудоемко.
Быстрее делать стандартное слияние через мастер слияния Word (у него кстати, нет ограничения на длину слияемого текста), но как известно Word не умеет разделять объединенный файл на отдельные файлы и давать названия таким файлам.

Если вариантов решения данной проблемы для вашего скрипта нет (из-за ограничения в 254 символа), то не могли бы вы посмотреть скрипт, который я нашел у англоязычной аудитории? Там тема поднималась много лет назад.
Я не понимаю в языке программирования и не могу понять в чем ошибка исполнения скрипта.

Их скрипт работает по другому принципу, описание работы скрипта есть в комментируемой части скрипта.
Краткая суть, слияние файлов происходит мастером слияния Word, а потом запускается макрос и объединенный файл делится на отдельные части.
В описании к скрипту указано, что первая строка должна иметь наименование файла, конец каждого файла должен иметь разрыв раздела (это можно найти в разделе «Макет страницы/Разрывы/Разрыв раздела на следующей странице»).

Делаю все как указано в их инструкции, но у меня появляется вот такая ошибка: Run-time error "5552": Выделенный фрагмент не содержит уровней заголовков. При нажатии на кнопку Debug в Word, то открывается Microsoft Visual Basic for Applications в котором подсвечивается проблемная часть кода " doc.Subdocuments.AddFromRange _
doc.Sections(secCounter).Range".
И тут не понятно, то ли ошибка в форматировании файла, то ли в коде скрипта.

На всякий случай прикладываю сами файлы (excel откуда берутся данные и вордовский файл).

Visual Basic
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
'purpose: save each letter generated after mail merge in a separate file
'         with the file name equal to first line of the letter.
'
'1. Before you run a mail merge make sure that in the main document you will 
'   end your letter with a Section Break (this can be found under 
'   Page Layout/Breaks/Section Break Next Page)
'2. Furthermore the first line of your letter contains the proposed file name
'   and put an enter after it. Make the font of the filename white, to make it 
'   is invisible to the receiver of the letter. You can also include a folder 
'   name if you like.
'3. Run the mail merge as usual. A file which contains all the letters is 
'   generated.
'4. Add this module to the generated mail merge file. Use Alt-F11 to go to the 
'   visual basic user interface, right click in the left pane on the generated
'   file and click on Import File and import this file
'5. save the generate file with all the letters as ‘Word Macro Enabled doc 
'   (*.docm)’.
'6. close the file.
'7. open the file again, click allow content when a warning about macro's is 
'   shown.
'8. execute the macro with the name SaveRecsAsFiles
 
 
Sub SaveRecsAsFiles()
    ' Convert all sections to Subdocs
    AllSectionsToSubDoc ActiveDocument
    'Save each Subdoc as a separate file
    SaveAllSubDocs ActiveDocument
End Sub
 
Private Sub AllSectionsToSubDoc(ByRef doc As Word.Document)
    Dim secCounter As Long
    Dim NrSecs As Long
    NrSecs = doc.Sections.Count
    'Start from the end because creating
    'Subdocs inserts additional sections
    For secCounter = NrSecs - 1 To 1 Step -1
        doc.Subdocuments.AddFromRange _
          doc.Sections(secCounter).Range
    Next secCounter
End Sub
 
Private Sub SaveAllSubDocs(ByRef doc As Word.Document)
    Dim subdoc As Word.Subdocument
    Dim newdoc As Word.Document
    Dim docCounter As Long
    Dim strContent As String, strFileName As String
 
    docCounter = 1
    'Must be in MasterView to work with
    'Subdocs as separate files
    doc.ActiveWindow.View = wdMasterView
    For Each subdoc In doc.Subdocuments
        Set newdoc = subdoc.Open
        'retrieve file name from first line of letter.
        strContent = newdoc.Range.Text
        strFileName = Mid(strContent, 1, InStr(strContent, Chr(13)) - 1)
        'Remove NextPage section breaks
        'originating from mailmerge
        RemoveAllSectionBreaks newdoc
        With newdoc
            .SaveAs FileName:=strFileName
            .Close
        End With
        docCounter = docCounter + 1
    Next subdoc
End Sub
 
Private Sub RemoveAllSectionBreaks(doc As Word.Document)
    With doc.Range.Find
        .ClearFormatting
        .Text = "^b"
        With .Replacement
            .ClearFormatting
            .Text = ""
        End With
        .Execute Replace:=wdReplaceAll
    End With
End Sub
Миниатюры
При слиянии в word из excel сохранить в отдельный файл с названиями по определенному полю  
Вложения
Тип файла: 7z Temp3.7z (31.0 Кб, 11 просмотров)
0
Модератор
Эксперт MS Access
 Аватар для shanemac51
12511 / 5085 / 814
Регистрация: 07.08.2010
Сообщений: 14,959
Записей в блоге: 4
02.05.2022, 12:22
Цитата Сообщение от Smailm Посмотреть сообщение
Вы предлагаете вручную дробить длинный текст на мелкие куски.
можно и программно, у меня как-то было более 11000 символов
0
0 / 0 / 0
Регистрация: 01.05.2022
Сообщений: 7
02.05.2022, 12:24
shanemac51, ваше предложение смотрится практично, так удобнее делать сопоставление, спасибо!
Но насколько я понимаю, это не решит проблему с ограничением в 256 символов.
0
Модератор
Эксперт MS Access
 Аватар для shanemac51
12511 / 5085 / 814
Регистрация: 07.08.2010
Сообщений: 14,959
Записей в блоге: 4
02.05.2022, 12:24
Цитата Сообщение от Smailm Посмотреть сообщение
который я нашел у англоязычной аудитории? Там тема поднималась много лет назад.
Я не понимаю в языке программирования и не могу понять в чем ошибка исполнения скрипта.
Их скрипт работает по другому принципу, описание работы скрипта есть в комментируемой части скрипта.
посмотрю, интересно чем он отличается от моего

Добавлено через 34 секунды
Цитата Сообщение от Smailm Посмотреть сообщение
Но насколько я понимаю, это не решит проблему с ограничением в 256 символов.
это вполне решаемо
0
0 / 0 / 0
Регистрация: 01.05.2022
Сообщений: 7
02.05.2022, 12:31
Цитата Сообщение от shanemac51 Посмотреть сообщение
посмотрю, интересно чем он отличается от моего
О, это был Ваш, код, сорри, я думал, что это код Punkt5.
Цитата Сообщение от shanemac51 Посмотреть сообщение
это вполне решаемо
Супер! Какой из двух скриптов лучше применить в моей ситуации?
Возможно скрипт, который я приложил, если он корректный, то вся работа ложится на мастер слияния Word.
Буду вам благодарен за помощь в решении вопроса.
0
малоболт
1328 / 510 / 213
Регистрация: 30.01.2020
Сообщений: 1,244
02.05.2022, 12:49
Цитата Сообщение от Smailm Посмотреть сообщение
Если я Вас правильно понял, то Вы предлагаете вручную дробить длинный текст на мелкие куски.
Вы неправильно поняли. Я уже выше дал вам решение проблемы ограничения в 254 символа.
Вам надо заменить 53 строку кода, который вы привели, как уже используемый вами. Вот эту:
Visual Basic
53
.Content.Find.Execute aWhatFind(ii), False, False, False, False, False, True, 1, False, aa(iRow,aColNums(ii)), 2
на соответствующий цикл:
Visual Basic
53
54
55
56
57
58
59
60
  wStr = aWhatFind(ii) 'то_что_ищем в word-шаблоне  = заведомо маленькое и заведомо НЕ ПОПАДАЮЩЕЕСЯ в том_на_что_меняем
  xStr = aa(iRow,aColNums(ii)) 'то_на_что_меняем (из excel-таблицы). Может быть велико
  Do While Len(xStr) > 250 'до тех пор пока то_на_что_меняем > 250 символов
    'меняем в цикле то_что_ищем на обрезок того_на_что_меняем + то_что_ищем на хвосте
    .Content.Find.Execute wStr, False, False, False, False, False, True, 1, False, left(xStr,250-len(wStr)) & wStr, 2 
    xStr = mid(xStr,251-len(wStr)) 'отрезаем то, что уже вставили от начала того_на_что_меняем
  loop
  .Content.Find.Execute wStr, False, False, False, False, False, True, 1, False, xStr, 2 'довставляем остаток
Добавив описание двух дополнительных переменных wStr, xStr в DIM в первой строке приведённого вами кода.

Добавлено через 1 минуту
Должно получиться:
Visual Basic
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
dim xls, wrd, FSO, Sha, xDir, wDir, sDir, xF, sFiles, xFiles, aa, aWhatFind, aColNums, wStr, xStr
  Const hdrRows=2 'Число строк заголовков, которые пропускать
  aWhatFind=Array("Имя файла","@Дата ENG","@Дата RUS","«Компания_ENG»","«Компания_RUS»","«Президент_ENG»","«Президент_RUS»","«ИПфизик_ENG»","«ИПфизик_RUS»","«ФИО_ENG»","«ФИО_RUS»","«Номер_и_дата_договора_ENG»","«Номер_и_дата_договора_RUS»","«Обязанности_ENG»","«Обязанности_RUS»","«Период_ENG»","«Период_RUS»","«Сумма_ENG»","«Сумма_RUS»") 'массив того, что искать в word-шаблоне
  aColNums =Array(1,12,13,7,6,8,9,5,4,2,3,14,15,11,10,16,17,18,19) 'массив номеров колонок Escel-файла для замены
  Set FSO = CreateObject("Scripting.FileSystemObject") 
  
  xDir = FSO.GetAbsolutePathname("") ' xlsx ищем в текущей папке
  sDir = xDir 'папка, где лежат шаблоны, пока пишем текущую папку 
  wDir = xDir 'папка, куда кладём готовый результат. пока в текущую
  with  CreateObject("Shell.Application")
    Set sFiles = .NameSpace(sDir).Items() 'всё что есть в папке шаблонов
    Set xFiles = .NameSpace(xDir).Items() 'пока то же
  end with
  sFiles.Filter 64, "*.dotx" 'смотрим в папке шаблонов на файлы с такой маской.
  if sFiles.Count < 1 Then 'ФАЙЛОВ НЕТ
    wsh.echo "Нет шаблонов В папке " & wDir
    wsh.quit
  end if
  xFiles.Filter 64, "*.xlsx" 'смотрим в папке xlsx только на файлы с такой маской.
  if xFiles.Count < 1 Then 'ФАЙЛОВ НЕТ
    wsh.echo "Нет файлов *.xlsx В папке " & xDir
    wsh.quit
  end if
 
  Set xls = CreateObject("Excel.Application")
  xls.Visible = True 'лучше потом поменять на false, чтобы Excel открывался невидимым
  Set wrd = CreateObject("Word.Application")
  wrd.Visible = True 'лучше потом поменять на false, чтобы Word  открывался невидимым
 
  for each xF in xFiles 'переберём все xlsx файлы
    With xls.WorkBooks.Open(xf.Path)
      aa = .Sheets(1).UsedRange.Value
      .Close
    end with
    for iRow = HdrRows+1 to uBound(aa) step 1
      xlRow2Wrd() ' обработаем каждую строку
    next
  next
  xls.quit 'закроем Excel
  wrd.quit 'закроем Word
  Set wrd=Nothing: Set xls=Nothing: Set FSO=Nothing: Set Sha=Nothing
  Set sFiles=Nothing: Set xFiles=Nothing: Set xF=Nothing 'очистим объекты
  wsh.echo "Я кончила! Твоя очередь." 
  wsh.quit
  
  Sub xlRow2Wrd()
  dim fName
  const Repl=""".,&@#№'<>"
  for each sF in sFiles
    with wrd.documents.Open(sF.Path)
      for ii = 0 to uBound(aColNums) step 1
        if aColNums(ii) <= uBound(aa,2) then
          wStr = aWhatFind(ii) 'то_что_ищем в word-шаблоне  = заведомо маленькое и заведомо НЕ ПОПАДАЮЩЕЕСЯ в том_на_что_меняем
          xStr = aa(iRow,aColNums(ii)) 'то_на_что_меняем (из excel-таблицы). Может быть велико
          do While Len(xStr) > 250 'до тех пор пока то_на_что_меняем > 250 символов
            'меняем в цикле то_что_ищем на обрезок того_на_что_меняем + то_что_ищем на хвосте
            .Content.Find.Execute wStr, False, False, False, False, False, True, 1, False, left(xStr,250-len(wStr)) & wStr, 2 
            xStr = mid(xStr,251-len(wStr)) 'отрезаем то, что уже вставили от начала того_на_что_меняем
          loop
          .Content.Find.Execute wStr, False, False, False, False, False, True, 1, False, xStr, 2 'довставляем остаток
        end if
      next
      fName = aa(iRow,aColNums(0))
      for ii=1 to Len(Repl) step 1
        fName = replace(fName,Mid(repl,ii,1),"")
      next
      .SaveAs FSO.BuildPath (wDir, fName),12 
      .Close
    end with
  next
end sub
P.S. Ваш файл .docx пересохраните как шаблон word (.dotx), чтобы скрипт с ним правильно работал.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
02.05.2022, 12:49

Как сохранить рисунок из Word'a в отдельный файл (*.bmp; *.jpg; *.gif ...)
Конечно, есть вариант сохранить страницу как html и просматривать папку .files. Но мне этот путь не очень нравиться... Cоздал...

Как, находясь в Excel и открыв из под него Word-овский файл, сохранить этот файл в другом формате?
Прошу помощи у знатоков VBA по 3-м вопросам: Буду очень благодарен за ответ. 1). Как, находясь в Excel и открыв из под него...

Сохранить табличный документ в файл Word или Excel
Доброго времени суток! Вопрос не знаете ли как сделать в форме отчета кнопку которая при нажатии дает возможность сохранить табличный...

Сохранить word файл из excel с именем взятым из определенной ячейки
Всем доброго времени суток, прошу подсказать макрос, который бы сохранял открытый word документ по пути &quot;C:\\Папка&quot; с именем...

беда! с правами при слиянии с документом Word
Вообщем дела обстаят так: я пользователь сетевого ресурса - диски z, x, k,.., имею права на запись и чтение, выложил базу на диск, создал...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru