Я не понимаю: «Когда я использую только код objAtt.SaveAsFile saveFolder
, файл не поврежден».
Если я не включаю имя файла в путь, SaveAsFile
всегда останавливается с ошибкойдля меня.Я перепробовал все варианты, которые только мог придумать, но ни один из них не сохранит файл.
У меня никогда не было SaveAsFile
повреждения файла.Моя теория состоит в том, что ваши электронные письма имеют более одного вложения, и вы сохраняете неправильное.Ваш код:
saveFolder = "C:\Users\acheng\Desktop"
For Each objAtt In itm.Attachments
objAtt.SaveAsFile saveFolder & "\Order_History_Report.xlsx"
Set objAtt = Nothing
Next
Если в письме есть два вложения, этот код будет:
- Сохранить первое вложение как «C: \ Users \ acheng \ Desktop \ Order_History_Report.xlsx »перезаписывает любой файл с таким именем, сохраненный со вчерашнего дня.
- Сохраните второе вложение как« C: \ Users \ acheng \ Desktop \ Order_History_Report.xlsx », перезаписав первое вложение.
В большинстве электронных писем сегодня используются изображения Html для логотипов и изображений, но в некоторых по-прежнему используются встроенные изображения, которые передаются в виде вложений, но не сообщаются пользователю в качестве вложений.
Приведенный ниже код проверит мою теорию.Скопируйте этот код в новый модуль:
Option Explicit
Public Sub InvestigateEmails()
Dim Exp As Explorer
Dim InxA As Long
Dim ItemCrnt As MailItem
Set Exp = Outlook.Application.ActiveExplorer
If Exp.Selection.Count = 0 Then
Call MsgBox("Pleaase select one or more emails then try again", vbOKOnly)
Exit Sub
Else
For Each ItemCrnt In Exp.Selection
With ItemCrnt
Debug.Print "From (Sender email address): " & .SenderEmailAddress
Debug.Print "Subject: " & .Subject
Debug.Print "Sent on: " & .SentOn
Debug.Print "Received: " & .ReceivedTime
If .Attachments.Count = 0 Then
Debug.Print "No attachments"
Else
Debug.Print "Attachments:"
Debug.Print "No.|Type|Path|Filename|DisplayName|"
For InxA = 1 To .Attachments.Count
With .Attachments(InxA)
Debug.Print InxA & "|";
Select Case .Type
Case olByValue
Debug.Print "Val";
Case olEmbeddeditem
Debug.Print "Ebd";
Case olByReference
Debug.Print "Ref";
Case olOLE
Debug.Print "OLE";
Case Else
Debug.Print "Unk;"
End Select
' Not all types have all properties. This code handles
' those missing properties of which I am aware. However,
' I have never found an attachment of type Reference or OLE.
' Additional code may be required for them.
Select Case .Type
Case olEmbeddeditem
Debug.Print "|";
Case Else
Debug.Print "|" & .PathName;
End Select
Debug.Print "|" & .Filename;
Debug.Print "|" & .DisplayName & "|"
End With
Next
End If
Debug.Print "--------------------------"
End With
Next
End If
End Sub
Чтобы использовать этот код, выберите одно или несколько писем, которые вы хотите обработать, и затем запустите InvestigateEmails
.Он выведет выбор свойств для каждого выбранного электронного письма.Ваше окно немедленного доступа будет выглядеть примерно так:
From (Sender email address): a.j.dallimore@MyIsp.com
Subject: Test
Sent on: 15/11/2018 11:22:41
Received: 15/11/2018 11:22:49
Attachments:
No.|Type|Path|Filename|DisplayName|
1|Val||002 View from back of Neville Tower.jpg|002 View from back of Neville Tower.jpg|
2|Val||image001.jpg|image001.jpg|
--------------------------
Я отправил вышеуказанное письмо самому себе.Вложение 1 было обычным вложением, которое было указано в заголовке и его можно было перетащить в папку или щелкнуть, чтобы открыть его.Вложение 2 было встроено и отображалось в виде картинки в теле письма, но не было указано в заголовке.
Моя теория состоит в том, что с учетом одного из ваших электронных писем InvestigateEmails
будет перечислять более одного вложения на одно электронное письмо, и последнее вложение не будет рабочей книгой Excel.Вы сохраняете это вложение с расширением «xlsx», поэтому Excel пытается и не может открыть его.
Кстати, я использую эту процедуру всякий раз, когда разрабатываю новый код для обработки электронных писем.Я мог бы запланировать, чтобы мой новый код запускался из события или правила, но эта процедура делает тестирование намного проще.Я изменяю этот код, чтобы вызвать новый код и выбрать простое электронное письмо.Когда я отладил свой код для работы с простым письмом, я попробую более сложный.Нет более простого способа контролировать, какие электронные письма передаются макросу для обработки.Я предлагаю вам сохранить этот макрос для дальнейшего использования.Кроме того, я могу сказать вам, где найти увеличенную версию, которая выводит текстовый файл на рабочем столе.
В остальной части этого ответа предполагается, что моя теория верна.Если моя теория неверна, возможно, нам придется продолжить исследование.
Прежде чем показать, как сохранить правильное вложение со статическим именем файла, я скажу, что сомневаюсь, что это хорошая идея.Если я правильно понимаю, каждый день вы получаете рабочую книгу, которая перезаписывает рабочую книгу предыдущего дня.Вы извлекаете данные из рабочей книги и сохраняете их в своей базе данных.Это может показаться хорошей идеей, но это может иметь катастрофические последствия.Несколько лет назад я знал о подобной ситуации, хотя, к счастью, я не был лично вовлечен.Как и вы, они получали файлы, извлекали данные и затем отбрасывали файлы.Казалось, все это работало в течение нескольких месяцев, но затем они обнаружили, что данные извлекаются неправильно.Если бы они сохранили исходные файлы, исправить их базу данных было бы сложно, но возможно.Но без исходных данных они ничего не могли сделать.
Я рекомендую вам сохранять файлы с именем, например: «Order_History_Report 181115.xlsx».Это позволит вам заархивировать все исходные файлы на случай необходимости их дальнейшей обработки в будущем.Обрабатывать файл с таким именем немного сложнее, но я могу объяснить, как это сделать.
Возвращаясь к вашему коду, самое простое исправление:
For Each objAtt In itm.Attachments
If LCase(Right$(objAtt.DisplayName, 4)) = ".xlsx" Then
objAtt.SaveAsFile saveFolder & "\Order_History_Report.xlsx"
Set objAtt = Nothing
Exit For
End If
Next
Этот код игнорирует все вложения, которые не являются обычными рабочими книгами, и, как только он нашел обычную рабочую книгу, он не ищетбольше.