This is my first post on Stack Overflow.
I have an Excel file that contains multiple sheets with data. Sheet "Emailer" contains buttons to hit the macro. The macro is working fine, while running it copies the defined sheets into new workbook and create an outlook email with attachment.
All is working fine, I would need a filter on a specific column to filter the data before copy and past into new workbook. Currently, all the data with no filter is copying. The specific column (M) is available in all 4 sheets that I want to filter (basis the value available under it) and copy paste.
Below is my code i am struggling with to achieve what i want.
Request to help and applgoies if i havent follow any rule of posting the question.
Thansk in advance.
Sub MIS_Mail()
Dim rng As Range
Dim rng2 As Range
Dim ws As Worksheet
Dim ws2 As Worksheet
Dim OutApp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim StrSignature As String
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 sh As Worksheet
Dim TheActiveWindow As Window
Dim TempWindow As Window
Set ws = Sheets("Emailer")
Set ws2 = Sheets("GROW MONEY")
Set rng = Nothing
'Set rng2 = Nothing
On Error Resume Next
'Only the visible cells in the selection
'Set rng = Selection.SpecialCells(xlCellTypeVisible)
'You can also use a fixed range if you want
Set rng = ws2.Range("A2:M34").SpecialCells(xlCellTypeVisible)
'Set rng2 = ws2.Range("B18:I33").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If rng Is Nothing Then
MsgBox "The selection is not a range or the sheet is protected" & _
vbNewLine & "please correct and try again.", vbOKOnly
Exit Sub
End If
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set Sourcewb = ActiveWorkbook
'Copy the ActiveSheet to a new workbook
With Sourcewb
Set TheActiveWindow = ActiveWindow
Set TempWindow = .NewWindow
.Sheets(Array("GROW MONEY", "Tranche wise details", "All products Deal limit status", "Delinquency")).Copy ' here i want to filter the data in all three sheets before 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 worksheet 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
Application.CutCopyMode = False
'Save the new workbook/Mail it/Delete it
TempFilePath = Environ$("temp") & "\"
TempFileName = Sourcewb.Name
strBody = "<font face=""Calibri"" size=""2"" color=""#1F497D"">" & "Dear All," & "<br> <br>" & _
"Please find attached MIS Report as on " & Format(ws2.Range("B1").Value, "DD-MMM-YY") & "." & "<br><br>" & "</font>"
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olMailItem)
On Error Resume Next
With Destwb
.SaveAs TempFilePath & TempFileName & FileExtStr, FileFormat:=FileFormatNum
On Error Resume Next
With OutMail
.To = ws.Range("C5").Value
.CC = ws.Range("D5").Value
.BCC = ""
.Subject = ws.Range("E5").Value
.HTMLBody = strBody & RangetoHTML(rng) '& RangetoHTML2(rng2) & vbNewLine '& StrSignature '& Signature
.Attachments.Add Destwb.FullName
.Display 'or use .Display
End With
On Error GoTo 0
.Close savechanges:=False
End With
Kill TempFilePath & TempFileName & FileExtStr
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Function RangetoHTML(rng As Range)
' Changed by Ron de Bruin 28-Oct-2006
' Working in Office 2000-2016
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "\" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to past the data in
rng.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML = ts.readall
ts.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
'Close TempWB
TempWB.Close savechanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function
Function RangetoHTML2(rng2 As Range)
' Changed by Ron de Bruin 28-Oct-2006
' Working in Office 2000-2016
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "\" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to past the data in
rng2.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML2 = ts.readall
ts.Close
RangetoHTML2 = Replace(RangetoHTML2, "align=center x:publishsource=", _
"align=left x:publishsource=")
'Close TempWB
TempWB.Close savechanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function
I have tried to do something with Autofilter with array() but not luckm here is the edited code:
Sub MIS_Mail()
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
'Don't forget to copy the function RangetoHTML in the module.
'Working in Excel 2000-2016
Dim rng As Range
Dim rng2 As Range
Dim ws As Worksheet
Dim ws2 As Worksheet
Dim OutApp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim StrSignature As String
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 sh As Worksheet
Dim TheActiveWindow As Window
Dim TempWindow As Window
Dim CatSites As String
Set ws = Sheets("Emailer")
Set ws2 = Sheets("GROW MONEY")
Set rng = Nothing
'Set rng2 = Nothing
On Error Resume Next
'Only the visible cells in the selection
'Set rng = Selection.SpecialCells(xlCellTypeVisible)
'You can also use a fixed range if you want
Set rng = ws2.Range("A2:M50").SpecialCells(xlCellTypeVisible)
'Set rng2 = ws2.Range("B18:I33").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If rng Is Nothing Then
MsgBox "The selection is not a range or the sheet is protected" & _
vbNewLine & "please correct and try again.", vbOKOnly
Exit Sub
End If
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set Sourcewb = ActiveWorkbook
'Copy the ActiveSheet to a new workbook
With Sourcewb
Set TheActiveWindow = ActiveWindow
Set TempWindow = .NewWindow
CatSites = "GROW"
.Sheets(Array("GROW MONEY", "Tranche wise details", "All products Deal limit status", "Delinquency")).AutoFilter
.Sheets(Array("GROW MONEY", "Tranche wise details", "All products Deal limit status", "Delinquency")).AutoFilter field:=13, Criteria1:=CatSites
.Sheets(Array("GROW MONEY", "Tranche wise details", "All products Deal limit status", "Delinquency")).SpecialCells(xlCellTypeVisible).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 worksheet 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
Application.CutCopyMode = False
'Save the new workbook/Mail it/Delete it
TempFilePath = Environ$("temp") & "\"
TempFileName = Sourcewb.Name
strBody = "<font face=""Calibri"" size=""2"" color=""#1F497D"">" & "Dear All," & "<br> <br>" & _
"Please find attached MIS Report as on " & Format(ws2.Range("B1").Value, "DD-MMM-YY") & "." & "<br><br>" & "</font>"
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olMailItem)
On Error Resume Next
With Destwb
.SaveAs TempFilePath & TempFileName & FileExtStr, FileFormat:=FileFormatNum
On Error Resume Next
With OutMail
.To = ws.Range("C2").Value
.CC = ws.Range("D2").Value
.BCC = ""
.Subject = ws.Range("E2").Value
.HTMLBody = strBody & RangetoHTML(rng) '& RangetoHTML2(rng2) & vbNewLine '& StrSignature '& Signature
.Attachments.Add Destwb.FullName
.Display 'or use .Display
End With
On Error GoTo 0
.Close savechanges:=False
End With
Kill TempFilePath & TempFileName & FileExtStr
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Function RangetoHTML(rng As Range)
' Changed by Ron de Bruin 28-Oct-2006
' Working in Office 2000-2016
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "\" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to past the data in
rng.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML = ts.readall
ts.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
'Close TempWB
TempWB.Close savechanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function
You could work with similar code as later in your Sub (usually not needed to post your entire sub if it's this long, just the bit you're struggling with)
Sub MIS_Mail()
Dim rng As Range, rng2 As Range
Dim ws As Worksheet, ws2 As Worksheet, sh As Worksheet, nsh As Worksheet
Dim OutApp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim StrSignature As String, FileExtStr As String, TempFilePath As String, TempFileName As String
Dim FileFormatNum As Long
Dim Sourcewb As Workbook, Destwb As Workbook
Dim TheActiveWindow As Window, TempWindow As Window
Dim shArray As Variant, arrSheet As Variant
Set ws = Sheets("Emailer")
Set ws2 = Sheets("GROW MONEY")
Set rng = Nothing
'Set rng2 = Nothing
On Error Resume Next
'Only the visible cells in the selection
'Set rng = Selection.SpecialCells(xlCellTypeVisible)
'You can also use a fixed range if you want
Set rng = ws2.Range("A2:M34").SpecialCells(xlCellTypeVisible)
'Set rng2 = ws2.Range("B18:I33").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If rng Is Nothing Then
MsgBox "The selection is not a range or the sheet is protected" & _
vbNewLine & "please correct and try again.", vbOKOnly
Exit Sub
End If
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set Sourcewb = ActiveWorkbook 'easier to declare these to copy the sheets while going through the for each loop after filtering them
Set Destwb = Workbooks.Add
Sourcewb.Activate
shArray = Array(Sheets("Tranche wise details"), Sheets("All products Deal limit status"), Sheets("Delinquency"), Sheets("GROW MONEY"))
For Each arrSheet In shArray 'Filter before you do the copying
Set sh = arrSheet
Set nsh = Destwb.Sheets.Add
nsh.Name = sh.Name
If sh.AutoFilterMode Then 'autofilter is 'on'
On Error Resume Next
sh.ShowAllData 'clearing existing filters
sh.Columns("M:M").Copy 'getting rid of the formulas first
sh.Columns("M:M").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
sh.Range("M1").AutoFilter Field:=13, Criteria1:="UGRO"
On Error GoTo 0
Else
sh.Columns("A:A").Copy
sh.Columns("A:A").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
sh.Range("M1").AutoFilter Field:=13, Criteria1:="UGRO" 'still not getting any errors here on the testfile
End If
sh.UsedRange.Copy nsh.Range("A1")
nsh.UsedRange.Copy
nsh.Range("A1").PasteSpecial xlPasteValues
Application.CutCopyMode = False
Next arrSheet
Application.DisplayAlerts = False
Destwb.Sheets(Destwb.Sheets.Count).Delete 'delete the sheet the workbook started with (depending on the language, these differ)
Application.DisplayAlerts = True
'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
Application.CutCopyMode = False
Destwb.Activate 'Destwb is ready to be mailed"
'Save the new workbook/Mail it/Delete it
TempFilePath = Environ$("temp") & "\"
TempFileName = Sourcewb.Name
strBody = "<font face=""Calibri"" size=""2"" color=""#1F497D"">" & "Dear All," & "<br> <br>" & _
"Please find attached MIS Report as on " & Format(ws2.Range("B1").Value, "DD-MMM-YY") & "." & "<br><br>" & "</font>"
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olMailItem)
On Error Resume Next
With Destwb
.SaveAs TempFilePath & TempFileName & FileExtStr, FileFormat:=FileFormatNum
On Error Resume Next
With OutMail
.To = ws.Range("C5").Value
.CC = ws.Range("D5").Value
.BCC = ""
.Subject = ws.Range("E5").Value
.HTMLBody = strBody & RangetoHTML(rng) '& RangetoHTML2(rng2) & vbNewLine '& StrSignature '& Signature
.Attachments.Add Destwb.FullName
.Display 'or use .Display
End With
On Error GoTo 0
.Close savechanges:=False
End With
Kill TempFilePath & TempFileName & FileExtStr
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Function RangetoHTML(rng As Range)
' Changed by Ron de Bruin 28-Oct-2006
' Working in Office 2000-2016
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "\" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to past the data in
rng.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML = ts.readall
ts.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
'Close TempWB
TempWB.Close savechanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function
Function RangetoHTML2(rng2 As Range)
' Changed by Ron de Bruin 28-Oct-2006
' Working in Office 2000-2016
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "\" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to past the data in
rng2.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML2 = ts.readall
ts.Close
RangetoHTML2 = Replace(RangetoHTML2, "align=center x:publishsource=", _
"align=left x:publishsource=")
'Close TempWB
TempWB.Close savechanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function
My Test Sub: ONLY USED ON YOUR TESTFILE, THIS IS NOT THE FULL SUB
Sub TESTMIS_Mail()
Dim rng As Range, rng2 As Range
Dim ws As Worksheet, ws2 As Worksheet, sh As Worksheet, nsh As Worksheet
Dim StrSignature As String, FileExtStr As String, TempFilePath As String, TempFileName As String
Dim FileFormatNum As Long
Dim Sourcewb As Workbook, Destwb As Workbook
Dim TheActiveWindow As Window, TempWindow As Window
Dim shArray As Variant, arrSheet As Variant
Set Sourcewb = ActiveWorkbook
Set Destwb = Workbooks.Add
Sourcewb.Activate
shArray = Array(Sheets("Tranche wise details"), Sheets("All products Deal limit status"), Sheets("Delinquency"), Sheets("GROW MONEY"))
For Each arrSheet In shArray 'Filter before you do the copying
Set sh = arrSheet
Set nsh = Destwb.Sheets.Add
nsh.Name = sh.Name
If sh.AutoFilterMode Then 'autofilter is 'on'
On Error Resume Next
sh.ShowAllData 'clearing existing filters
sh.Range("M1").AutoFilter Field:=13, Criteria1:="UGRO"
On Error GoTo 0
Else
sh.Range("M1").AutoFilter Field:=13, Criteria1:="UGRO"
End If
sh.UsedRange.Copy nsh.Range("A1")
nsh.UsedRange.Copy
nsh.Range("A1").PasteSpecial xlPasteValues
Next arrSheet
Application.DisplayAlerts = False
Destwb.Sheets(Destwb.Sheets.Count).Delete
Application.DisplayAlerts = True
'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
Application.CutCopyMode = False
Destwb.Activate
End Sub
Hope this is what you were looking for.
Related
I am hoping someone can help I have the below code which is pasting a new row into a new worksheet in SharePoint with a table. However when it is pasted into the next blank row the table is not changing dynamically with it. Can you please assist.
Sub Complete()
Dim tb1 As ListObject, tb2 As ListObject, tbl As ListObject
Dim Lrow As Long, dRow As Long
Dim ws As Worksheet, ws1 As Worksheet
Dim searchRange As Range, foundCell As Range
Dim mysearch As String
Dim wb As Workbook, Scwb As Workbook
Dim ScRow As Range
Application.DisplayAlerts = False
Set wb = ThisWorkbook
mysearch = Sheets("OI").Range("D4").Value
Set ws = wb.Sheets("OI")
Set tb1 = ws.ListObjects("OITs")
Set tb2 = wb.Sheets("TDets").ListObjects("OIFinal")
Lrow = tb2.ListRows.Count
With ws
.Range("A:A").EntireColumn.Hidden = False
End With
tb1.Range.AutoFilter Field:=11, Criteria1:="<>" & vbNullString
NumRows = tb1.DataBodyRange.Cells.SpecialCells(xlCellTypeVisible).Rows.Count
tb1.DataBodyRange.Cells.SpecialCells(xlCellTypeVisible).Copy
tb2.DataBodyRange(Lrow + 1, 1).PasteSpecial xlPasteValues
Application.CutCopyMode = False
tb1.DataBodyRange.Columns(4).Resize(, 7).ClearContents
tb1.Range.AutoFilter Field:=11, Criteria1:="=" & vbNullString
With ws
.Range("A:A").EntireColumn.Hidden = True
End With
With wb.Sheets("CReqs")
Set searchRange = .Range("G1", .Range("G" & .Rows.Count).End(xlUp))
End With
Set Scwb = Workbooks.Open("https://*****.sharepoint.com/sites/*****/Shared%20Documents/General/NAA/Apps.xlsx")
Set tbl = Scwb.Sheets("AppAccs").ListObjects("Pending")
dRow = tbl.Range.Rows.Count
Set foundCell = searchRange.Find(what:=mysearch, Lookat:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not foundCell Is Nothing Then
foundCell.Offset(0, 6).Value = "Yes"
foundCell.Offset(0, -6).EntireRow.Copy Destination:=tbl.Range(dRow, "A").Offset(1) ' This is the line that pastes the code to a new wb but does not expand the table.
Scwb.Save
Scwb.Close
Else
MsgBox "We cannot find the ID " & mysearch & " to send for approval. Please check ID."
End If
Application.DisplayAlerts = True
End Sub
I have resolved the above by simply adding tbl.Resize tbl.Range.CurrentRegion to the next line after pasting across to the new SP workbook
Sub OpenFile()
Dim temp_fdr As String
Dim test_fdr As String
Dim model_selector As String
Dim path As String
Dim Keyword_range As Range
'--------------------------------------------------------복사 할 영역 선택 변수
Dim Cont_R, Mov_T, Mov_V, Open_V As String
Dim Cont_R_row, Mov_T_row, Mov_V_row, Open_V_row, Test_T_row As Integer
Dim Cont_R_col, Mov_T_col, Mov_V_col, Open_V_col, Test_T_col As Integer
Dim realDataStartRow As Integer
Dim realDataEndRow As Long
Dim t1Rng As Range
Dim t2Rng As Range
Dim t3Rng As Range
Dim t4Rng As Range
Dim t5rng As Range
Dim t1Arr, t2Arr, t3Arr, t4Arr, t5Arr
'------------------------------------------------------- 시험 폴더 지정을 위한 변수 선언
today_total = Format(Date, "yyyy-mm-dd")
today_year = Format(Year(Date), "0000")
today_month = Format(Month(Date), "00")
today_day = Format(Day(Date), "00")
Dim lastModifiedFdr As String
'-------------------------------------------------------- 그래프 오리지널 폴더 -------------------나중에 바꿀 path
Dim chtWorkbookPath As String
Dim chtWorkbook As Workbook
Dim chtSheet As Worksheet
chtWorkbookPath = ThisWorkbook.path
Debug.Print chtWorkbookPath
'Set chtWorkbook = "C:\Users\bjkwack\Desktop\실시간그래프도식화작업중\" & today_year & "-" & today_month & ".xlsm"
' Debug.Print chtWorkbook
'-------------------------------------------------------- 현재 시험폴더 찾아가기------------------------------
' lastModifiedFdr = Module2.lastModifiedFdr
'MsgBox lastModifiedFdr
If Len(lastModifiedFdr) = 0 Then
temp_fdr = "\\172.30.145.135\evr data\" & today_year & "-" & today_month & "\" & today_day & "\"
lastModifiedFdr = Module2.LastFolder(temp_fdr)
End If
test_fdr = "\\172.30.145.135\evr data\" & today_year & "-" & today_month & "\" & today_day & "\" & lastModifiedFdr & "\"
'MsgBox test_fdr
'-----------------------------------------------------------------------------------------
'---------------------------------------------------------------------------------------- 시험 파일 위치지정
On Error Resume Next
Application.DisplayAlerts = False
Workbooks.Open Filename:=test_fdr & "\" & today_total & ".xls", ReadOnly:=True
Application.DisplayAlerts = True
Debug.Print test_fdr
Debug.Print lastModifiedFdr
'Workbooks("" & today_total & ".xls").Sheets(1).Activate
With ActiveSheet.UsedRange '---------------------------------------------------------- s = 출력물에서 2월 데이터 영역
Set Keyword_range = .Find(What:="접촉저항", LookAt:=xlWhole) '--------------------- 접촉저항 행 열 요소 찾기
On Error Resume Next
'Cont_R_row = Keyword_range.Row
On Error Resume Next
Cont_R_col = Keyword_range.Column
Debug.Print Cont_R_col
Set Keyword_range = .Find(What:="동작시간(ms)", LookAt:=xlWhole) '--------------------- 동작시간 행 열 요소 찾기
On Error Resume Next
'Mov_T_row = Keyword_range.Row
On Error Resume Next
Mov_T_col = Keyword_range.Column
Debug.Print Mov_T_col
Set Keyword_range = .Find(What:="석방전압(V)", LookAt:=xlWhole) '--------------------- 개방전압 행 열 요소 찾기
On Error Resume Next
'Open_V_row = Keyword_range.Row
On Error Resume Next
Open_V_col = Keyword_range.Column + 1 '--------------------*** 실제 데이터 열 보다 한칸 +1 에 있음 ***********
Set Keyword_range = .Find(What:="흡인전압(V)", LookAt:=xlWhole) '--------------------- 동작전압 행 열 요소 찾기
On Error Resume Next
'Mov_V_row = Keyword_range.Row
On Error Resume Next
Mov_V_col = Keyword_range.Column + 1 '--------------------*** 실제 데이터 열 보다 한칸 +1 에 있음 ***********
Set Keyword_range = .Find(What:="시험시간", LookAt:=xlWhole) '--------------------- 시험시간 행 열 요소 찾기
'On Error Resume Next
Test_T_row = Keyword_range.Row
Test_T_col = Keyword_range.Column
Debug.Print Test_T_row
Debug.Print Test_T_col
realDataStartRow = .Cells(Test_T_row, Test_T_col).End(xlDown).Row
realDataEndRow = .Cells(Rows.Count, Test_T_col).End(xlUp).Row
Debug.Print realDataStartRow
Debug.Print realDataEndRow
Set t1Rng = .Range(Cells(realDataStartRow, Test_T_col), Cells(realDataEndRow, Test_T_col))
Set t2Rng = .Range(Cells(realDataStartRow, Cont_R_col), Cells(realDataEndRow, Cont_R_col))
Set t3Rng = .Range(Cells(realDataStartRow, Mov_T_col), Cells(realDataEndRow, Mov_T_col))
Set t4Rng = .Range(Cells(realDataStartRow, Mov_V_col), Cells(realDataEndRow, Mov_V_col))
Set t5rng = .Range(Cells(realDataStartRow, Open_V_col), Cells(realDataEndRow, Open_V_col))
Debug.Print t1Rng
t1Arr = t1Rng.Value
t2Arr = t2Rng.Value
t3Arr = t3Rng.Value
t4Arr = t4Rng.Value
t5Arr = t5rng.Value
Debug.Print t2Arr
Debug.Print t3Arr
.Range("ab5").Resize(UBound(t1Arr, 1)).Value = t1Arr
.Range("ac5").Resize(UBound(t2Arr, 1)).Value = t2Arr
.Range("ad5").Resize(UBound(t3Arr, 1)).Value = t3Arr
.Range("ae5").Resize(UBound(t4Arr, 1)).Value = t4Arr
.Range("af5").Resize(UBound(t5Arr, 1)).Value = t5Arr
End With
' Selection.NumberFormatLocal = "h:mm:ss;#"
End Sub
You can use Application.Transpose to copy values from a column into a row
Dim rng As Range
'set the source range
Set rng = Range("A1:A5")
'copy to a column
Range("C1").Resize(rng.Rows.Count, 1).Value = rng.Value
'copy to a row
Range("E1").Resize(1, rng.Rows.Count).Value = Application.Transpose(rng.Value)
Note there's an upper limit to the size of the array you can transpose (~65k items I think)
I have a simple VBA script in Outlook 2019, script zips an attachment before sending an email, creates a new email, attaches an attachment, and sends it to the recipient. My goal is to save selected data to SQL database, Such as .To,From and zip archive as binaryattachment.zip. I have a problem finding a command to send INSERT INTO to the database, is there such a possibility?
VBA script:
#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal milliseconds As LongPtr) 'MS Office 64 Bit
#Else
Private Declare Sub Sleep Lib "kernel32" (ByVal milliseconds As Long) 'MS Office 32 Bit
#End If
Function FileExists(FilePath As String) As Boolean
Dim TestStr As String
TestStr = ""
On Error Resume Next
TestStr = Dir(FilePath)
On Error GoTo 0
If TestStr = "" Then
FileExists = False
Else
FileExists = True
End If
End Function
Sub MainFunction()
Const cstrFolderAttachment As String = "C:\attachments\"
'Test 32/64 bit
Dim PathZipProgram As String
PathZipProgram = "C:\Program Files\7-Zip\7z.exe"
If Not FileExists(PathZipProgram) Then
PathZipProgram = "C:\Program Files (x86)\7-Zip\7z.exe"
End If
'Password lenght
Const cintLenghtPassword As Integer = 8
'User signature file
Const cstrFileSigntature As String = "signature.htm"
Dim objMail As Outlook.MailItem
Dim objNewMail1 As Outlook.MailItem
Dim objNewMail2 As Outlook.MailItem
Dim objAttachment As Attachment
Dim objWord As Object
Dim objDocument As Object
Dim objFSO As Object
Dim objTextStream As Object
Dim strTo As String
Dim strSubject As String
Dim strBody As String
Dim strCommand As String
Dim strFilePath As String
Dim objWordRange As Object
Dim strMessage As String
Dim objApp As Object
Dim objInsp As Object
'Set objApp = GetObject("", "Outlook.Application")
'Set objInsp = objApp.ActiveInspector.CurrentItem
Dim signature As String
Dim objNS As Outlook.NameSpace
Dim objFolderItem As Outlook.Folder
Select Case Application.ActiveWindow.Class
Case olExplorer
Set objMail = ActiveExplorer.Selection.Item(1)
Case olInspector
Set objMail = ActiveInspector.CurrentItem
End Select
strMessage = "Subject: " & objMail.Subject & vbCrLf & vbCrLf & "Message: " & vbCrLf & objMail.Body
'Clear subfolder
On Error Resume Next
Kill cstrFolderAttachment & "*.*"
Kill cstrFolderAttachment & "Zip\*.*"
On Error GoTo 0
Set objMail = Application.ActiveInspector.CurrentItem
Set objNS = Application.GetNamespace("MAPI")
Set objFolderItem = objNS.Folders.Item("name.surname#domaind.com").Folders.Item("Temp")
objMail.Move objFolderItem
objDokument.Close False
'clear variables
Set objDokument = Nothing
Set objWord = Nothing
'save all attechments to folder
For Each objAttachment In objMail.Attachments
objAttachment.SaveAsFile cstrFolderAttachment & objAttachment.FileName
Next objAttachment
'7zip comprimation
strSource = cstrFolderAttachment & "*.*"
strDestination = cstrFolderAttachment & "Zip\attachment.zip"
strPassword = RandomPassword(cintLenghtPassword)
strCommand = """" & PathZipProgram & """ a -tzip """ & strCil & _
""" -p" & strPassword & " """ & strSource & """"
Shell strCommand
'Application.Wait (Now + TimeSerial(0, 0, cintBreak))
Call Sleep(1000 * cintBreak)
'FSO
strstrFilePath = Environ("appdata") & _
"\Microsoft\Signatures\" & cstrFileSigntature
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextStream = _
objFSO.GetFile(cstrFileSigntature).OpenAsTextStream(1, -2)
strSignature = objTextStream.ReadAll
objTextStream.Close
'clear variables
Set objTextStream = Nothing
Set objFSO = Nothing
Set objNewMail1 = Application.CreateItem(olMailItem)
With objNewMail1
'To
For Each recip In objMail.Recipients
Set newRecip = .Recipients.Add(recip.Address)
newRecip.Type = recip.Type
Next
.Subject = strSubject
.BodyFormat = olFormatHTML
.HTMLBody = strSignature
.Attachments.Add cstrFolderAttachment & "Zip\attachment.zip"
.Display
.Send
End With
objNewMail1.Close olSave
'clear variables
Set objMail = Nothing
Set objNewMail1 = Nothing
i = MsgBox("Email sended.", , "info box")
End Sub
Private Function RandomPassword(Delka As Integer)
'Dave Hawley
Dim i As Integer
Dim strHeslo As String
Randomize
For i = 1 To Lenght
If i Mod 2 = 0 Then
strPassword = Chr(Int((90 - 65 + 1) * Rnd + 65)) & strPassword
Else
strPassword = Int((9 * Rnd) + 1) & strPassword
End If
Next i
RandomPassword = strPassword
End Function
Database structure:
ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
to_email VARCHAR(100) NOT NULL,
from_email VARCHAR(100) NOT NULL,
attachment VARBINARY(MAX) NOT NULL,
date_create DATETIME NOT NULL,
file_size INT NOT NULL
I'm working on a macro that loops through all files in a folder, changes formulas that point to other workbooks to values, and saves and closes each file. I've merged two pieces of code from Ron de Bruin into the below macro. His code to break links and change to values works perfectly when it isn't in the loop but when I run this macro the files then don't have the info, they instead return "#N/A". What am I doing wrong?
Sub Formulas()
Const strSavePath As String = “MyFilePath"
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String, Fnum As Long
Dim mybook As Workbook
Dim CalcMode As Long
Dim sh As Worksheet
Dim ErrorYes As Boolean
Dim Path1 As Range
Set Path1 = ThisWorkbook.Worksheets("Monthly Reporting").Range("E2")
Dim WorkbookLinks As Variant
Dim i As Long
MyPath = strSavePath & Path1 & "\"
'Add a slash at the end if the user forget it
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
'If there are no Excel files in the folder exit the sub
FilesInPath = Dir(MyPath & "*.xl*")
If FilesInPath = "" Then
MsgBox "No files found"
Exit Sub
End If
'Fill the array(myFiles)with the list of Excel files in the folder
Fnum = 0
Do While FilesInPath <> ""
Fnum = Fnum + 1
ReDim Preserve MyFiles(1 To Fnum)
MyFiles(Fnum) = FilesInPath
FilesInPath = Dir()
Loop
'Change ScreenUpdating, Calculation and EnableEvents
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
'Loop through all files in the array(myFiles)
If Fnum > 0 Then
For Fnum = LBound(MyFiles) To UBound(MyFiles)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(MyPath & MyFiles(Fnum))
On Error GoTo 0
If Not mybook Is Nothing Then
'Change cell value(s) in one worksheet in mybook
WorkbookLinks = mybook.LinkSources(Type:=xlLinkTypeExcelLinks)
If IsArray(WorkbookLinks) Then
For i = LBound(WorkbookLinks) To UBound(WorkbookLinks)
mybook.BreakLink _
Name:=WorkbookLinks(i), _
Type:=xlLinkTypeExcelLinks
Next i
Else
MsgBox "No Links to other workbooks"
End If
If Err.Number > 0 Then
ErrorYes = True
Err.Clear
'Save and close mybook
mybook.Close savechanges:=True
End If
On Error GoTo 0
Else
'Not possible to open the workbook
ErrorYes = True
End If
Next Fnum
End If
If ErrorYes = True Then
MsgBox "There are problems in one or more files, possible problem:" _
& vbNewLine & "protected workbook/sheet or a sheet/range that not exist"
End If
'Restore ScreenUpdating, Calculation and EnableEvents
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
End Sub
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.