Предыстория, так, на всякий. Имеется умная таблица, с данными для формирования писем в Outlook по галочке. Галочка служит индикатором для заполнения форм "Кому"; "Копии"; "Тема" - по каждой галочке создается письмо и все на данный момент ОК.
Хочу добавить следующее:
В файле-примере есть столбец Документы. В реальной рабочей книге там номера; эти номера уникальные, повторяющихся нет. На данный момент 1 строка = 1 номер. Так же, в этом столбце не должно быть пропусков (если только не ошибка).
В принципе, я догадываюсь, как подтягивать по имени (т.е. номеру) документа аналогично названный pdf файл из специально созданной для этого папки (важно: в макросе, который в примере, я это еще не дописал). Но дело в том, что на данный момент я знаю, как создать письмо для каждого уникального номера; т.е. 80 номеров - 80 писем и 80 файлов в нем, и т.д.. Но это не совсем корректно. Нужно, чтобы учитывалось следующее. Если для разных документов (их номеров) соответствуют одинаковый адресат (т.е. "кому") и одинаковое описание проекта (т.е. "тема"), то логично, что не нужно создавать отдельное письмо для каждого пдф, а создать одно письмо и залить туда все соответствующие документы.
И вот мой вопрос в том, как это сделать
Получилось очень длинное объяснение, наверное, можно было короче объяснить.
Простите за поздний ответ, пытался разобраться своими силами. До Вашего ответа я про словари не знал, сейчас почитал про них; насколько понял, 1 ключ = 1 элемент, к тому же каждый ключ уникален, тогда как это может помочь в текущей ситуации, можете подробней рассказать?
Ниже просто рассуждения вслух. Необходимо, чтобы если в выборке по галочкам ячейка столбца Contact Person одной строки совпадал с ячейкой столбца Contact Person в другой строке и при этом еще совпадали темы письма (названия проектов), макрос бы создал письмо по данным, которые увидит раньше, и залил бы туда уже два аттачмента, номера которых будут указаны. Если темы строк совпадают, но адресаты не совпадают - разные письма с аттачментом в каждом. Если совпадают адресаты, но не совпадают темы - аналогично.
И как же тут правильно применить словарь? Ведь если сделать ключом тему письма, то рано или поздно попадется дубликат, и непременно вылезет ошибка.
Элементом может служить не только простое значение (числовое, текстовое), но и массив и объект (тот же словарь - получится словарь словарей - я использую в том случае, если ключ составной (по нескольким параметрам), а на сцепку (текстовый ключ) не полагаюсь по каким-либо причинам). В данном случае от Вас требуется определить, что будет являться ключом. Допустим, если Вы хотите сгруппировать письма по названию темы, то формируете ключ по ней, а в значение по ключу:
Код
sKey = sTheme & "|" & sEmail
заносите в массив элементов, допустим: словарь или динамический массив (если повторов нет) полных имён прикрепляемых файлов; адресат; текст письма. Для примера наполнение описанного словаря будет выглядеть так:
Код
if dictPost.Exists(sKey) then
arrDictItem = dictPost(sKey)
arrAttaches = arrDictItem(2)
ReDim Preserve arrAttaches(0 to Ubound(arrAttaches) + 1)
arrAttaches(Ubound(arrAttaches)) = sFullAttachName
arrDictItem(2) = arrAttaches
dictPost(sKey) = arrDictItem
else
dictPost(sKey) = VBA.Array(sEmail, sTheme, VBA.Array(sFullAttachName))
end if
Когда полностью сформировали словарь, то в цикле по нему формируете и отправляете письма.
Изменено: JayBhagavan - 23.11.2018 05:44:05(изменил код - логическая ошибка в блоке if dictPost.Exists(sKey) ... end if)
Формула массива (ФМ) вводится Ctrl+Shift+Enter Memento mori
Если ключ уже существует, то мы присваиваем ключу трехмерный массив, который содержит в себе адресат, тему письма и массив прикрепляемых документов; А вот в случае "иначе" - я не совсем понял.
Вот что у меня получилось на данный момент:
Скрытый текст
Код
Sub Example()
Dim dicPost
Dim row As Integer
Dim sKey As String, sItem As String, sFullAttachName As String
Set dicCountry = CreateObject("Scripting.Dictionary")
With Sheets("Лист1").Range("B3:B15")
For row = 1 To .Rows.Count
sFullAttachName = .Cells(row, 8).Value
sEmail = .Cells(row, 2).Value
sTheme = .Cells(row, 4).Value
sKey = sEmail & "|" & sTheme
sItem = sFullAttachName
dicPost.item(sKey) = sItem
MsgBox dicPost("sKey")
Next
End With
End Sub
Это все промежуточное, просто хотелось понять, как работает словарь. В данном случае он не выдает ошибки, так как если встречается дубликат, то он остается, а предыдущий стирается.
Я хотел бы уточнить, поправьте меня, пожалуйста, если я не прав. Для того, чтобы отправлять письма так, как нужно мне, необходимо написать код по следующим шагам:
1. Создать словарь (словарь состоит из ключей и элементов в нем); 2. Обозначить диапазон, из которого будут формироваться ключи и элементы для словаря (в моем случае это "галочки" в столбце B): 3. Объявить по каждой галочке ключ, допустим, sKey, который состоит из Value sEmail (адресат) и sTheme (тема письма); 4. Предотвратить ошибку при совпадении ключей; 5. Добавить к каждому ключу массив элементов (элементы это название документа(-ов), которые мне необходимо прикрепить). 6. Словарь таким образом сформируется; 7. По каждому ключу словаря создать письмо.
Option Explicit
Sub Example()
Dim dictPost: Set dictPost = CreateObject("Scripting.Dictionary")
Dim row As Integer
Dim sKey As String, sEmail As String, sTheme As String, sFullAttachName As String
Dim arrAttaches(), arrDictItem()
With Sheets("Лист1").Range("B3:B15")
For row = 1 To .Rows.Count
If .Cells(row, 1).Value = "a" Then
sFullAttachName = .Cells(row, 8).Value
sEmail = .Cells(row, 2).Value
sTheme = .Cells(row, 4).Value
sKey = sEmail & "|" & sTheme
If dictPost.Exists(sKey) Then
arrDictItem = dictPost(sKey)
arrAttaches = arrDictItem(2)
ReDim Preserve arrAttaches(0 To UBound(arrAttaches) + 1)
arrAttaches(UBound(arrAttaches)) = sFullAttachName
arrDictItem(2) = arrAttaches
dictPost(sKey) = arrDictItem
Else
dictPost(sKey) = VBA.Array(sEmail, sTheme, VBA.Array(sFullAttachName))
End If
End If '.Cells(row, 1).Value = "a"
Next
End With
For row = 0 To dictPost.Count - 1
arrDictItem = dictPost.Items()(row)
sEmail = arrDictItem(0)
sTheme = arrDictItem(1)
arrAttaches = arrDictItem(2)
Debug.Print "To: " & sEmail,
Debug.Print "Subj: " & sTheme,
Debug.Print "Attaches: " & Join(arrAttaches, ", ")
Next
End Sub
Формула массива (ФМ) вводится Ctrl+Shift+Enter Memento mori
Я применил это, так сказать, на беловике, всё работает, как и хотелось. В рабочей версии изменил диапазон, добавил массивы для CC и массивы с текстом. Не хватит слов, чтобы выразить благодарность. Спасибо большое, пусть Вам сопутствует успех. Мне неловко, что Вам пришлось писать за меня код, и очень жаль, что самому не хватило ума.
Framed, после первого моего знакомства на форуме со словарями, я только через год решился использовать их. И первую программу, которая выводила на экран фразу "Привет, мир!" я написал только после того, как мне показали как её написать. Посему считаю Вам не за что стыдиться, т.к. я не с нуля для Вас что-то написал, а немного исправил Ваш код. Пожалуйста и успеха.
Формула массива (ФМ) вводится Ctrl+Shift+Enter Memento mori