I am using the following script to take information from an email body as a 1D and put it into excel. It was working well but recently it has started throwing an error when it comes to pasting the range. I think it is a simple problem with defining the range but I can't understand why? I have tried a few ways of doing it and it always fails somewhere. Sample data here: http://pastebin.com/mXZAWD90
The code is triggered from outlook, if this makes a difference?
Sub _to_excel()
On Error GoTo 0
Set myOlApp = Outlook.Application
Set mynamespace = myOlApp.GetNamespace("mapi")
Dim ThermoMail As Outlook.MailItem
Set ThermoMail = Application.ActiveInspector.CurrentItem
On Error Resume Next
Set xlObj = GetObject(, "Excel.Application")
On Error GoTo 0
If xlObj = Empty Then Set xlObj = CreateObject("Excel.Application")
xlObj.Visible = True
xlObj.Workbooks.Add
Dim msgText, delimtedMessage, Delim1 As String
delimtedMessage = ThermoMail.Body
'Remove everything before "Lead Source:" and after "ELMS"
TrimmedArray = Split(delimtedMessage, "Source:")
delimtedMessage = TrimmedArray(1)
TrimmedArray = Split(delimtedMessage, "ELMS")
delimtedMessage = TrimmedArray(0)
TrimmedArray = Split(delimtedMessage, "Address:")
TrimmedArray(1) = Replace(TrimmedArray(1), ",", vbCrLf)
delimtedMessage = TrimmedArray(0) & "Address:" & TrimmedArray(1)
Dim pasteRange As Range
'Split the array at each return
messageArray = Split(delimtedMessage, vbCrLf)
'PROBLEMS START HERE
'paste the split array into the worksheet
lastRow = UBound(messageArray) + 1
pasteRange = ActiveSheet.Range(Cells(1, 1), Cells(lastRow, 1))
ActiveSheet.pasteRange = WorksheetFunction.Transpose(messageArray)
Call splitAtColons
ThermoMail.Close (olDiscard)
End Sub
You're missing a Set statement and pasteRange is not a property of Activesheet - it is a Range variable, so:
Set pasteRange = ActiveSheet.Range(Cells(1, 1), Cells(lastRow, 1))
pasteRange.Value = WorksheetFunction.Transpose(messageArray)
#Siddharth Rout's suggestion was the answer. I properly defined activesheet using Dim ws As Worksheet and then was able to eliminate the use of pasteRange. I think the problems partially stemmed from issues using ActiveSheet when the code was triggered from outlook.
Sub Thermo_to_excel()
On Error GoTo 0
Set myOlApp = Outlook.Application
Set mynamespace = myOlApp.GetNamespace("mapi")
Dim ThermoMail As Outlook.MailItem
Set ThermoMail = Application.ActiveInspector.CurrentItem
On Error Resume Next
Set xlObj = GetObject(, "Excel.Application")
On Error GoTo 0
If xlObj = Empty Then Set xlObj = CreateObject("Excel.Application")
xlObj.Visible = True
xlObj.Workbooks.Add
Dim ws As Worksheet
Set ws = Sheets("Sheet1")
Dim msgText, delimtedMessage, Delim1 As String
delimtedMessage = ThermoMail.Body
'Remove everything before "Lead Source:" and after "ELMS"
TrimmedArray = Split(delimtedMessage, "Source:")
delimtedMessage = TrimmedArray(1)
TrimmedArray = Split(delimtedMessage, "ELMS")
delimtedMessage = TrimmedArray(0)
TrimmedArray = Split(delimtedMessage, "Address:")
TrimmedArray(1) = Replace(TrimmedArray(1), ",", vbCrLf)
delimtedMessage = TrimmedArray(0) & "Address:" & TrimmedArray(1)
'Split the array at each return
messageArray = Split(delimtedMessage, vbCrLf)
'paste the split array into the worksheet
lastRow = UBound(messageArray) + 1
ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, 1)).Value = WorksheetFunction.Transpose(messageArray)
Call splitAtColons
ThermoMail.Close (olDiscard)
End Sub
Edit
Try this
Sub Thermo_to_excel()
Dim myOlApp As Object, mynamespace As Object
Dim ThermoMail As Object
Dim msgText, delimtedMessage, Delim1 As String
Dim oXLApp As Object, oXLWb As Object, oXLWs As Object
Set myOlApp = Outlook.Application
Set mynamespace = myOlApp.GetNamespace("mapi")
Set ThermoMail = Application.ActiveInspector.CurrentItem
delimtedMessage = ThermoMail.Body
'~~> Establish an EXCEL application object
On Error Resume Next
Set oXLApp = GetObject(, "Excel.Application")
'~~> If not found then create new instance
If Err.Number <> 0 Then
Set oXLApp = CreateObject("Excel.Application")
End If
Err.Clear
On Error GoTo 0
Set oXLWb = oXLApp.Workbooks.Add
Set oXLWs = oXLWb.Sheets("Sheet1")
'Remove everything before "Lead Source:" and after "ELMS"
TrimmedArray = Split(delimtedMessage, "Source:")
delimtedMessage = TrimmedArray(1)
TrimmedArray = Split(delimtedMessage, "ELMS")
delimtedMessage = TrimmedArray(0)
TrimmedArray = Split(delimtedMessage, "Address:")
TrimmedArray(1) = Replace(TrimmedArray(1), ",", vbCrLf)
delimtedMessage = TrimmedArray(0) & "Address:" & TrimmedArray(1)
'Split the array at each return
messageArray = Split(delimtedMessage, vbCrLf)
'paste the split array into the worksheet
lastRow = UBound(messageArray) + 1
With oXLWs
.Range(.Cells(1, 1), .Cells(lastRow, 1)).Value = _
oXLApp.WorksheetFunction.Transpose(messageArray)
End With
Call splitAtColons
ThermoMail.Close (olDiscard)
End Sub
Related
I fetch email addresses from my Outlook account.
Now I am trying to fetch only specific email address from inbox e.g. Gmail.com that returns gmail addresses only.
I modified the code where I used array to store the addresses temporarily and then compare to string. After altering the code it returns nothing (not even errors).
Option Explicit
Sub GetInboxItems()
Dim ol As outlook.Application
Dim ns As outlook.Namespace
Dim fol As outlook.Folder
Dim I As Object
Dim mi As outlook.MailItem
Dim N As Long
Dim val As String
Dim MyArray() As String, MyString As String, J As Variant, K As Integer
Dim MyAs As Variant
Dim Awo As Variant
MyString = Worksheets("Inbox").Range("D1")
MyArray = Split(MyString, ";")
Application.ScreenUpdating = False
Set ol = New outlook.Application
Set ns = ol.GetNamespace("MAPI")
Set fol = ns.GetDefaultFolder(olFolderInbox)
'Dim inputSheet As Worksheet
'Dim aCellOnInputSheet As Range
'Dim inputDateCell As Range
'Dim userSheetName As String
'Set cod = ThisWorkbook.Worksheets("Inbox")
'Set aCellOnInputSheet = cod.Range("D1")
'userSheetName = aCellOnInputSheet.Value
Range("A3", Range("A3").End(xlDown).End(xlToRight)).Clear
N = 2
For Each I In fol.Items
If I.Class = olMail Then
Set mi = I
N = N + 1
If mi.SenderEmailType = "EX" Then
MyAs = Array(mi.Sender.GetExchangeUser().PrimarySmtpAddress)
For Each Awo In MyAs
If InStr(MyString, Awo) > 0 Then
Cells(N, 1).Value = mi.Sender.GetExchangeUser().PrimarySmtpAddress
Cells(N, 2).Value = mi.SenderName
Exit For
End If
Next
' Cells(N, 1).Value = mi.Sender.GetExchangeUser().PrimarySmtpAddress
' Cells(N, 2).Value = mi.SenderName
Else
MyAs = Array(mi.SenderEmailAddress)
For Each Awo In MyAs
If InStr(MyString, Awo) > 0 Then
Cells(N, 1).Value = mi.SenderEmailAddress
Cells(N, 2).Value = mi.SenderName
Exit For
End If
Next
End If
End If
Next I
Application.ScreenUpdating = True
End Sub
Fetching all email addresses will be problematic. I don't want to expose any email domains other than the defined ones.
Minimal changes to manipulating the row n and switching the variables in Instr should be sufficient.
This also shows how to drop the array if one domain.
Option Explicit
Sub GetInboxItems_SingleDomain()
' Early binding - reference to Microsoft Outlook XX.X Object Library required
Dim ol As Outlook.Application
Dim ns As Outlook.Namespace
Dim fol As Outlook.Folder
Dim folItm As Object
Dim mi As Outlook.MailItem
Dim n As Long
Dim myString As String
Dim myAddress As String
myString = Worksheets("Inbox").Range("D1") ' gmail.com
'Debug.Print myString
Application.ScreenUpdating = False
Set ol = New Outlook.Application
Set ns = ol.GetNamespace("MAPI")
Set fol = ns.GetDefaultFolder(olFolderInbox)
Range("A3", Range("A3").End(xlDown).End(xlToRight)).Clear
n = 3
' If slow, limit the number of items in the loop
' e.g. https://stackoverflow.com/questions/21549938/vba-search-in-outlook
' strFilter = "#SQL=" & Chr(34) & "urn:schemas:httpmail:fromemail" & Chr(34) & " like '%" & myString & "'"
For Each folItm In fol.Items
If folItm.Class = olMail Then
Set mi = folItm
If mi.SenderEmailType = "EX" Then
myAddress = mi.Sender.GetExchangeUser().PrimarySmtpAddress
Else
myAddress = mi.SenderEmailAddress
End If
'Debug.Print myAddress
'The bigger text on the left
' In general, not necessarily here, keep in mind case sensitivity
If InStr(LCase(myAddress), LCase(myString)) > 0 Then
Cells(n, 1).Value = myAddress
Cells(n, 2).Value = mi.SenderName
n = n + 1
End If
End If
Next folItm
Application.ScreenUpdating = True
Debug.Print "Done."
End Sub
I'm new to VBA and I'm trying to scrape data from a website. I've used nested loop. When the innermost loop finishes for the first time, the next loop starts for marakez.
Actual problem is that when 'for each in schl2' loop repeats for second time, IE crashes and loop is unable to proceed. I have mentioned in code.
Here is my code
Sub ResultDownloader()
' here I define elemnts for the loop
Dim sht As Worksheet
Set sht = ThisWorkbook.Sheets("LocData")
Dim LastRow As Long
Dim i As Long
Dim imagePath As Object
LastRow = sht.Cells(sht.Rows.Count, "D").End(xlUp).Row
startrec = sht.Cells(sht.Rows.Count, "E").End(xlUp).Row
startrec = startrec + 1
Dim IE As Object
Dim Doc As HTMLDocument
' Set IE = CreateObject("InternetExplorer.Application")
Set IE = CreateObject("InternetExplorer.Application")
' here I define Object to sendkeys
Dim SHELL_OBJECT
SHELL_OBJECT = "WScript.Shell"
Set objShell = CreateObject(SHELL_OBJECT)
Record2Strt = (sht.Cells(sht.Rows.Count, "E").End(xlUp).Row) + 1
IE.Visible = True
IE.Navigate "some_url"
Do While IE.Busy
Application.Wait DateAdd("s", 1, Now)
Loop
Dim HTMLdoc As HTMLDocument
Dim selectElement, selectElement2, selectElement3 As HTMLSelectElement
Dim evtChange As Object
Set Doc = IE.Document
Dim dist1, tehsl1, mrkz1, schl1 As Object
Dim dist2, tehsl2, mrkz2, schl2 As Variant
Dim distlen, thsllen, mrkzlen, schllen As Byte
Dim dst, tsl, mrkz, schl As Byte
Dim elt3, elt4, elt5, elt6 As Variant
Set evtChange = Doc.createEvent("HTMLEvents")
evtChange.initEvent "change", True, False
Set dist1 = Doc.querySelector("Select[name=districts]")
Set dist2 = dist1.querySelectorAll("option")
distlen = dist1.querySelectorAll("option").Length
dst = 0
For Each elt3 In dist2
distnme = elt3.innerText
If distnme <> "All Districts" Then
dist1.getElementsByTagName("option")(dst).Selected = True
Set selectElement2 = Doc.getElementsByTagName("option")(dst)
selectElement2.dispatchEvent evtChange
Application.Wait DateAdd("s", 0.5, Now)
Set tehsl1 = Doc.querySelector("Select[name=tehsil]")
Set tehsl2 = tehsl1.querySelectorAll("option")
thsllen = tehsl1.querySelectorAll("option").Length
tsl = 0
For Each elt4 In tehsl2
thslnme = elt4.innerText
If thslnme <> "All Tehsils" Then
Set tehsl1 = Doc.querySelector("Select[name=tehsil]")
tehsl1.getElementsByTagName("option")(tsl).Selected = True
Set selectElement3 = tehsl1.getElementsByTagName("option")(tsl)
selectElement3.dispatchEvent evtChange
Application.Wait DateAdd("s", 0.5, Now)
Set mrkz1 = Doc.querySelector("Select[name=markaz]")
Set mrkz2 = mrkz1.querySelectorAll("option")
mrkzlen = mrkz1.querySelectorAll("option").Length
mrkz = 0
For Each elt5 In mrkz2
mrkznm = elt5.innerText
If mrkznm <> "All Marakez" Then
Set mrkz1 = Doc.querySelector("Select[name=markaz]")
mrkz1.getElementsByTagName("option")(mrkz).Selected = True
Set selectElement4 = mrkz1.getElementsByTagName("option")(mrkz)
selectElement4.dispatchEvent evtChange
Application.Wait DateAdd("s", 0.5, Now)
Set schl1 = Doc.querySelector("Select[name=school]")
Set schl2 = schl1.querySelectorAll("option")
schllen = schl1.querySelectorAll("option").Length
schl = 0
' second loop problem
' when for each elt6 in schl2 starts IE crashes
On Error Resume Next
For Each elt6 In schl2
Application.Wait DateAdd("s", 0.5, Now)
schlnm = elt6.innerText
If schlnm <> "All Schools" Then
Set schl1 = Doc.querySelector("Select[name=school]")
schl1.getElementsByTagName("option")(schl).Selected = True
Set selectElement5 = schl1.getElementsByTagName("option")(schl)
selectElement5.dispatchEvent evtChange
sht.Range("A" & LastRow + 1).Value = LastRow
sht.Range("B" & LastRow + 1).Value = distnme
sht.Range("C" & LastRow + 1).Value = thslnme
sht.Range("D" & LastRow + 1).Value = mrkznm
sht.Range("E" & LastRow + 1).Value = schlnm
LastRow = LastRow + 1
End If 'for school
schl = schl + 1
If schllen = schl Then
GoTo new_marakez
On Error Resume Next
End If
Next 'ele6
End If 'for marakez
new_marakez:
mrkz = mrkz + 1
If mrkzlen = mrkz Then
Exit For
GoTo new_tehsil
End If
Next 'ele5
On Error Resume Next
End If 'for tehsils
new_tehsil:
tsl = tsl + 1
If thsllen = tsl Then
GoTo new_dist
End If
Next 'ele4
On Error Resume Next
End If 'for districts
new_dist:
dst = dst + 1
If distlen = dst Then
GoTo stopp
End If
Next 'ele 3
On Error Resume Next
stopp:
End Sub
There is apparently a bug when using querySelectorAll with a generic object for your elements, in your case here 'schl2.', and using a for each...next loop. I solved this by using a standard for...next loop basically limiting the for loop, in your case, schl2.Length - 1. However, this will not work unless you define schl2 as MSHTML.IHTMLDOMChildrenCollection. If you leave this as generic, the schl2.Length will be NULL. The code below shows how I got around the problem.
`'Create html object to hold IE Document
Set html = IE.Document
Debug.Print "********* GET FIELDS ******" & vbCrLf
Dim res1 As MSHTML.IHTMLDOMChildrenCollection
Set res1 = html.querySelectorAll("#HtmlOutputReportResults2_Explorer_Filters_Column option:checked")
For r = 0 To res1.Length - 1
If res1(r).innerText <> "..." Then
Debug.Print "res1.Text: " & res1(r).innerText
End If
Next
Debug.Print vbCrLf & "********* GET OPERATORS ******" & vbCrLf
Dim res2 As MSHTML.IHTMLDOMChildrenCollection
Set res2 = html.querySelectorAll("#HtmlOutputReportResults2_Explorer_Filters_Operator option:checked")
For r = 0 To res2.Length - 1
If res2(r).innerText <> "..." Then
Debug.Print "res2.Text: " & res2(r).innerText
End If
Next`
I am trying to design a macro to search for multiple strings in an excel.
I have the following code which searches for the word "techno" in an excel but, I need to include a variable into the code so that I can search for multiple words such "Techno", "electromagnetic", "waves", etc. at once. I am unable to create a loop for this condition.
Can anyone suggest a solution to this problem? The below code works fine but, only a tweak is required to include multiple strings in the search.
Sub SearchFolders()
Dim xFso As Object
Dim xFld As Object
Dim xStrSearch As String
Dim xStrPath As String
Dim xStrFile As String
Dim xOut As Worksheet
Dim xWb As Workbook
Dim xWk As Worksheet
Dim xRow As Long
Dim xFound As Range
Dim xStrAddress As String
Dim xFileDialog As FileDialog
Dim xUpdate As Boolean
Dim xCount As Long
myArray = Array("techno", "magnetic", "laser", "trent")
On Error GoTo ErrHandler
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a forlder"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
xUpdate = Application.ScreenUpdating
Application.ScreenUpdating = False
Set xOut = Worksheets.Add
For myCounter = 0 To UBound(myArray)
MsgBox myCounter & " is the Count No."
xStrSearch = myArray(myCounter)
MsgBox xStrSearch & " is the Value fr String search"
xRow = 1
With xOut
.Cells(xRow, 1) = "Workbook"
.Cells(xRow, 2) = "Worksheet"
.Cells(xRow, 3) = "Cell"
.Cells(xRow, 4) = "Text in Cell"
Set xFso = CreateObject("Scripting.FileSystemObject")
Set xFld = xFso.GetFolder(xStrPath)
xStrFile = Dir(xStrPath & "*.xls*")
Do While xStrFile <> ""
Set xWb = Workbooks.Open(Filename:=xStrPath & "\" & xStrFile, UpdateLinks:=0, ReadOnly:=True, AddToMRU:=False)
For Each xWk In xWb.Worksheets
Set xFound = xWk.UsedRange.Find(xStrSearch)
MsgBox xFound & " is the strings found"
If Not xFound Is Nothing Then
xStrAddress = xFound.Address
End If
Do
If xFound Is Nothing Then
Exit Do
Else
xCount = xCount + 1
MsgBox xCount & " is the count of strings"
xRow = xRow + 1
.Cells(xRow, 1) = xWb.Name
.Cells(xRow, 2) = xWk.Name
.Cells(xRow, 3) = xFound.Address
.Cells(xRow, 4) = xFound.Value
End If
Set xFound = xWk.Cells.FindNext(After:=xFound)
MsgBox xFound & " next string"
MsgBox xStrAddress & " is the address "
MsgBox xFound.Address & " is the address found"
Loop While xStrAddress <> xFound.Address 'To check how xStrAddress is populated or do we need to declare it as a help from excel pointed out
myCounter = myCounter + 1
Next
xWb.Close (False)
xStrFile = Dir
Loop
.Columns("A:D").EntireColumn.AutoFit
End With
Next myCounter
MsgBox xCount & "cells have been found", ,
ExitHandler:
Set xOut = Nothing
Set xWk = Nothing
Set xWb = Nothing
Set xFld = Nothing
Set xFso = Nothing
Application.ScreenUpdating = xUpdate
Exit Sub
ErrHandler:
MsgBox Err.Description, vbExclamation
Resume ExitHandler
End Sub
If the strings you are searching will always be the same, hard code them into an array and Loop through the array elements to search each string, like so:
Dim myArray as Variant
Dim myCounter as Long
myArray = Array("techno", "electromagnetic", ...etc.)
For myCounter = 0 To UBound(myArray)
... 'your code here
xStrSearch = myArray(myCounter)
... 'the rest if your code here
Next myCounter
I have a master file having different account details. I am trying to make a code that will send a copy of the workbook after deleting unnecessary account details and mail it. It is working fine for one sheet but when I am using array for multiple sheets it is giving me object doesn't support method in this line of code ".DisplayPageBreaks = False".
Here is my code:
Sub Mail_Sheets_Array()
'Working in Excel 2000-2016
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
Dim FileExtStr As String
Dim FileFormatNum As Long
Dim Sourcewb As Workbook
Dim Destwb As Workbook
Dim TempFilePath As String
Dim TempFileName As String
Dim OutApp As Object
Dim OutMail As Object
Dim sh As Worksheet
Dim TheActiveWindow As Window
Dim TempWindow As Window
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set Sourcewb = ActiveWorkbook
'Copy the sheets to a new workbook
'We add a temporary Window to avoid the Copy problem
'if there is a List or Table in one of the sheets and
'if the sheets are grouped
With Sourcewb
Set TheActiveWindow = ActiveWindow
Set TempWindow = .NewWindow
.Sheets(Array("REC_INT", "REC_EXT")).Copy
End With
'Close temporary Window
TempWindow.Close
Set Destwb = ActiveWorkbook
'Determine the Excel version and file extension/format
With Destwb
If Val(Application.Version) < 12 Then
'You use Excel 97-2003
FileExtStr = ".xls": FileFormatNum = -4143
Else
'You use Excel 2007-2016
Select Case Sourcewb.FileFormat
Case 51: FileExtStr = ".xlsx": FileFormatNum = 51
Case 52:
If .HasVBProject Then
FileExtStr = ".xlsm": FileFormatNum = 52
Else
FileExtStr = ".xlsx": FileFormatNum = 51
End If
Case 56: FileExtStr = ".xls": FileFormatNum = 56
Case Else: FileExtStr = ".xlsb": FileFormatNum = 50
End Select
End If
End With
'Change all cells in the worksheets to values if you want
For Each sh In Destwb.Worksheets
sh.Select
With sh.UsedRange
.Cells.Copy
.Cells.PasteSpecial xlPasteValues
.Cells(1).Select
End With
Application.CutCopyMode = False
Destwb.Worksheets(1).Select
Next sh
'Save the new workbook/Mail it/Delete it
TempFilePath = Environ$("temp") & "\"
TempFileName = "Part of " & Sourcewb.name & " " & Format(Now, "dd-mmm-yy h-mm-ss")
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Dim Firstrow As Long
Dim Lastrow As Long
Dim Lrow As Long
Dim prow As Long
Dim r As Long
Dim x As Long
Dim y As Long
Dim CalcMode As Long
Dim ViewMode As Long
r = 0
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
'We use the ActiveSheet but you can replace this with
With Destwb.Sheets(Array("REC_INT", "REC_EXT"))
' With ActiveSheet
'We select the sheet so we can change the window view
.Select
'If you are in Page Break Preview Or Page Layout view go
'back to normal view, we do this for speed
ViewMode = ActiveWindow.View
ActiveWindow.View = xlNormalView
'Turn off Page Breaks, we do this for speed
.DisplayPageBreaks = False
'Set the first and last row to loop through
Firstrow = .UsedRange.Cells(1).Row
Lastrow = .UsedRange.Rows(.UsedRange.Rows.Count).Row
'We loop from Lastrow to Firstrow (bottom to top)
For Lrow = 9 To Lastrow Step 1
'We check the values in the A column in this example
With .Cells(Lrow, "C")
If Not IsError(.Value) Then
If Cells(Lrow, "D").Value = "Total" Then
GoTo y
End If
If .Value = Sheet1.Cells(2, 6) Then
r = r + 1
End If
If .Value <> Sheet1.Cells(2, 6) Then
If .Value = "" Then
r = 0
End If
prow = Lrow - r
If Cells(prow, "C").Value = Sheet1.Cells(2, 6) Then
r = r + 1
GoTo x
End If
.EntireRow.ClearContents
'This will delete each row with the Value "ron"
'in Column A, case sensitive.
x:
End If
End If
End With
Next Lrow
End With
ActiveWindow.View = ViewMode
With Application
.ScreenUpdating = True
.Calculation = CalcMode
End With
y:
Range(Cells(9, 3), Cells(Lrow, 3)). _
SpecialCells(xlCellTypeBlanks).EntireRow.Delete
'xxxxxxxxxxxxxxxxxx
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With Destwb
.SaveAs TempFilePath & TempFileName & FileExtStr, FileFormat:=FileFormatNum
On Error Resume Next
With OutMail
.To = "hadi#siemens.com"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = "Hi there"
.Attachments.Add Destwb.FullName
'You can add other files also like this
'.Attachments.Add ("C:\test.txt")
'.Send 'or use
.Display
End With
On Error GoTo 0
.Close savechanges:=False
End With
'Delete the file you have send
Kill TempFilePath & TempFileName & FileExtStr
Set OutMail = Nothing
Set OutApp = Nothing
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
You are trying to run a property only supported on a specified sheet, on multiple sheets at once. This is not supported, hence the error 438.
You can try to loop these sheets:
For Each ws In Destwb.Sheets
If ws.Name = "REC_INT" or ws.Name = "REC_EXT" then
Destwb.Worksheets(ws.Name).DisplayPageBreaks = False
End if
Next ws
I think you don't need to check for the sheets names, as you copy just the two of them into a new workbook.
I've been doing some VBA stuff lately but i don't know what directions to take.
Someone here helped me with the copy to Word, i've lost the topic but thanks a lot!
Is there a better way to read in the BookMarks and how can i get them to link the right sheet in this line;
MyArray(i)
'needs to go in to;
wb.worksheet(Myarray(i)).range("A1:BA3000")
I've been spending way to many hours on the array part.
Private Sub ranges()
Dim NamedRange As name
Dim nm As name
Dim ws As Worksheet
Dim Lr As Long
Dim Lc As Long
Dim Rng As range
Dim Bm As name
Dim wb As Workbook
Dim Fill As range
Dim wd As Word.Application
Set wd = New Word.Application
Set wb = ThisWorkbook 'Workbooks("C:\Excel")
Set aWs = ActiveSheet
'array with names of the word bookmarks
Dim myArray(38)
myArray(0) = ("Tappunten")
myArray(1) = ("test1")
myArray(2) = ("Groslijst")
myArray(3) = ("J01_2")
myArray(4) = ("D01")
myArray(5) = ("D03")
myArray(6) = ("W01")
myArray(7) = ("W02")
myArray(8) = ("W03")
myArray(9) = ("W04")
myArray(10) = ("M01")
myArray(11) = ("M03")
myArray(12) = ("M04")
myArray(13) = ("M05")
myArray(14) = ("HJ01")
myArray(15) = ("J01")
myArray(16) = ("M02")
myArray(17) = ("J03")
myArray(18) = ("J04")
myArray(19) = ("J05")
myArray(20) = ("J06")
myArray(21) = ("J07")
myArray(22) = ("J08")
myArray(23) = ("J09")
myArray(24) = ("J10")
myArray(25) = ("J11")
myArray(26) = ("J12")
myArray(27) = ("J13")
myArray(28) = ("J14")
myArray(29) = ("J15")
myArray(30) = ("OT03")
myArray(31) = ("OT06")
myArray(32) = ("OT07")
myArray(33) = ("Checklist")
myArray(34) = ("ObjectGegevens")
myArray(35) = ("Grondstof")
myArray(36) = ("Drinkwaterinstallatie")
myArray(37) = ("WTB")
myArray(38) = ("Warmwaterleidingnet")
'array for the worksheets on the excel sheets
Dim myArray2(38)
myArray2(0) = Worksheets(1).name
myArray2(1) = Worksheets(1).name
myArray2(2) = Worksheets(42).name
myArray2(3) = Worksheets(17).name
myArray2(4) = Worksheets(2).name
myArray2(5) = Worksheets(15).name
myArray2(6) = Worksheets(22).name
myArray2(7) = Worksheets(3).name
myArray2(8) = Worksheets(28).name
myArray2(9) = Worksheets(29).name
myArray2(10) = Worksheets(4).name
myArray2(11) = Worksheets(6).name
myArray2(12) = Worksheets(29).name
myArray2(13) = Worksheets(46).name
myArray2(14) = Worksheets(7).name
myArray2(15) = Worksheets(16).name
myArray2(16) = Worksheets(5).name
myArray2(17) = Worksheets(13).name
myArray2(18) = Worksheets(12).name
myArray2(19) = Worksheets(47).name
myArray2(20) = Worksheets(9).name
myArray2(21) = Worksheets(13).name
myArray2(22) = Worksheets(14).name
myArray2(23) = Worksheets(14).name
myArray2(24) = Worksheets(32).name
myArray2(25) = Worksheets(1).name
myArray2(26) = Worksheets(1).name
myArray2(27) = Worksheets(1).name
myArray2(28) = Worksheets(1).name
myArray2(29) = Worksheets(8).name
myArray2(30) = Worksheets(19).name
myArray2(31) = Worksheets(33).name
myArray2(32) = Worksheets(18).name
myArray2(33) = Worksheets(27).name
myArray2(34) = Worksheets(25).name
myArray2(35) = Worksheets(36).name
myArray2(36) = Worksheets(26).name
myArray2(37) = Worksheets(20).name
myArray2(38) = Worksheets(38).name
i = 1
For Each nm In ThisWorkbook.Names
If nm.Visible Then
Set NamedRange = wb.Names.Item(i)
Set ws = NamedRange.RefersToRange.Parent
End If
Lr = wb.worksheet(Myarray(i)).range("A1:BA3000").Find(What:="*", _ LookIn:=xlValues, _
SearchOrder:=xlByRows, _ SearchDirection:=xlPrevious,
SearchFormat:=False).Row
Lc = wb.worksheet(Myarray(i)).range("A1:BA3000").Find(What:="*", _ LookIn:=xlValues, _
SearchOrder:=xlByColumns, _ SearchDirection:=xlPrevious, _
SearchFormat:=False).Column
Set Rng = ws.range(ws.Cells(1, 1), ws.Cells(Lr, Lc))
With wd
.Visible = True
.WindowState = wdWindowStateMaximize
With .Documents.Add(Template:="C:\RABP sjabloon clean.dotx")
With .Bookmarks
myArray(i).range.PasteExcelTable LinkedToExcel:=False, _
WordFormatting:=True, RTF:=False
Rng.Copy ws.range(i)
End With
End With
End With
i = i + 1
Next nm
End Sub
There are 2 ways that you could populate your array:
Method 1:
myArray = Split("Tappunten test1 Groslijst ...", " ")
Method 2:
Sub LoopThroughBookmarks()
Dim oBookmark As Bookmark
Dim myArray() As String
ReDim Preserve myArray(0)
For Each oBookmark In ActiveDocument.Bookmarks
ReDim Preserve myArray(UBound(myArray) + 1)
myArray(UBound(myArray) - 1) = oBookmark.Name
Next
End Sub
The bookmarks will be entered in the order in which they occur in the document, you may want to add some validation for the bookmarks so that you don't add some by mistake.
I've no idea how to match the bookmarks to the 2nd array :-/
I've ended up using these 2 pieces of code;
Sub Copy_to_word()
Dim wdApp As New Word.Application
Dim wdDoc As Word.Document
Dim i As Long
Dim names As Range
Application.ScreenUpdating = False
Application.EnableEvents = False
'location of the word template
Const StrDocNm As String = "C:\Word template V2.0.dotx"
If Dir(StrDocNm) = "" Then Debug.Print "file missing"
If Dir(StrDocNm) = MsgBox "Template not found"
If Dir(StrDocNm) = "" Then Exit Sub
'Could probebly make it a bit neather
Set wdDoc = wdApp.Documents.Add(Template:=StrDocNm)
wdApp.Visible = True
'All the named ranges have the same name as the bookmark
With ThisWorkbook
For i = 1 To .names.Count
On Error GoTo LosseCell:
.names(i).RefersToRange.Copy
Debug.Print .names(i).Name
'When the range is copied it starts the next macro.
'if there's an error it goes tot the next name range
Call PasteBookmark(wdDoc, .names(i).Name)
LosseCell:
Next
End With
Set wdDoc = Nothing: Set wdApp = Nothing
'because it takes some time it had the events and screenupdating turned off
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
The second marcro is the part that pastes the range in to word;
Sub PasteBookmark(wdDoc As Word.Document, strBkMk As String)
Dim wdRng As Word.Range
With wdDoc
Application.ScreenUpdating = True 'not sure if this helps to be honest
Application.EnableEvents = True 'not sure if this helps to be honest
If .Bookmarks.Exists(strBkMk) Then
Set wdRng = .Bookmarks(strBkMk).Range
wdRng.Paste
.Bookmarks.Add strBkMk, wdRng
End If
End With
Set wdRng = Nothing
End Sub
Because the ranges vary in size i also have a macro that resizes the named ranges that can vary in row count;
Sub RangesAanpassen()
Dim NmdRngNames As Variant
Dim myLastRow As Long
Dim StrWsNaam As String
Dim strRangeNaam As String
Dim namRange As Name
Dim wsRange As Worksheet
Dim n As Variant
'the ranges that need to be resized are named the same as the sheets there
'on. It gave a lot of troubles because the sheets had names like "D01".
'Had to change all of them to a name that didn't look like a cell.
NmdRngNames = Array("D_03", "D_01", "J_01", "_6.4.3_Temperatuurmetingen",
"WTB", "Tappunten", "_6.4.2_Tappunten_inv", "Voorblad")
Application.ScreenUpdating = False
Application.EnableEvents = False
For Each n In NmdRngNames
strRangeNaam = n
On Error GoTo NextN: when the range is empty a "no object" error shows.
Set namRange = ActiveWorkbook.names.Item(strRangeNaam)
Set wsRange = Range(strRangeNaam).Worksheet
With wsRange
'the last cell can be anywhere in columns A to Z.
myLastRow = .Columns("A:Z").Find(What:="*", LookIn:=xlValues, _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByRows).Row
End With
With namRange
.RefersTo = wsRange.Range(wsRange.Cells(1, 1), _
wsRange.Cells(myLastRow, 1))
End With
NextN:
Next
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Thanks for the great forum!