VBA to copy specific sheet to existing book - vba

The task here is two fold (the first part already works though).
Task 1: Copy a sheet that's been selected from a combo box into a new document.
Task 2: Copy a specific sheet from the original document and add it to the new document that was created above.
So far I've got this: (but the second task doesn't work)
Sub Extract()
Dim wbkOriginal As Workbook
Set wbkOriginal = ActiveWorkbook
'sets site and engineer details into the estate page that is being extracted
Worksheets(FrontPage.CmbSheet.Value).Range("B3").Value = Worksheets("front page").Range("E6")
Worksheets(FrontPage.CmbSheet.Value).Range("D3").Value = Worksheets("front page").Range("N6")
Worksheets(FrontPage.CmbSheet.Value).Range("F3").Value = Worksheets("front page").Range("K6")
Worksheets(FrontPage.CmbSheet.Value).Range("B4").Value = Worksheets("front page").Range("F8")
Worksheets(FrontPage.CmbSheet.Value).Range("D4").Value = Worksheets("front page").Range("K8")
' copies sheet name from combo box into new document, saves it with site name and current date
' into C:\Temp\ folder for ease of access
With ActiveWorkbook.Sheets(FrontPage.CmbSheet.Value)
.Copy
ActiveWorkbook.SaveAs _
"C:\temp\" _
& .Cells(3, 2).Text _
& " " _
& Format(Now(), "DD-MM-YY") _
& ".xlsm", _
xlOpenXMLWorkbookMacroEnabled, , , , False
End With
Dim wbkExtracted As Workbook
Set wbkExtracted = ActiveWorkbook
Workbooks(wbkOriginal.Name).Sheets(DOCUMENTS).Copy _
After:=Workbooks(wbkExtracted.Name).Sheets(wbkExtracted.Name).Sheets.Count
'code to close the original workbook to prevent accidental changes etc
'Application.DisplayAlerts = False
'wbkOriginal.Close
'Application.DisplayAlerts = True
End Sub
I'm hoping one of you clever folks out there can tell me what I'm doing wrong :)

I think I know the problem you are running into. (Maybe) If you are working with a new instance of excel you need to save it then reopen it. It must have something to do with the object model. I had to do this not too long ago. Here is a snippet of the code I used.
Set appXL = New Excel.application
appXL.Workbooks.Add
Set wbThat = appXL.ActiveWorkbook
wbThat.application.DisplayAlerts = False
wbThat.SaveAs Filename:=strFilePath & "\" & strFileName
'This code needed to allow the copy function to work
wbThat.Close savechanges:=True
Set wbThat = Nothing
Set wbThat = application.Workbooks.Open(strFilePath & "\" & strFileName)
appXL.Quit
Set appXL = Nothing
'Copy Help page from this workbook to the report
wbThis.Sheets("Help").Copy after:=wbThat.Sheets(wbThat.Sheets.Count)

Sub Full_Extract()
Dim wbkOriginal As Workbook
Set wbkOriginal = ActiveWorkbook
'sets site and engineer details into the estate page that is being extracted
Worksheets(Sheet1.CmbSheet.Value).Range("B3").Value = Worksheets("front page").Range("E6")
Worksheets(Sheet1.CmbSheet.Value).Range("D3").Value = Worksheets("front page").Range("N6")
Worksheets(Sheet1.CmbSheet.Value).Range("F3").Value = Worksheets("front page").Range("K6")
Worksheets(Sheet1.CmbSheet.Value).Range("B4").Value = Worksheets("front page").Range("F8")
Worksheets(Sheet1.CmbSheet.Value).Range("D4").Value = Worksheets("front page").Range("K8")
' copies sheet name from combo box into new document, saves it with site name and current date
' into C:\Temp\ folder for ease of access
With ActiveWorkbook.Sheets(Array((Sheet1.CmbSheet.Value), "Z-MISC"))
.Copy
ActiveWorkbook.SaveAs _
"C:\temp\" _
& ActiveWorkbook.Sheets(Sheet1.CmbSheet.Value).Cells(3, 2).Text _
& " " _
& Format(Now(), "DD-MM-YY") _
& ".xlsm", _
xlOpenXMLWorkbookMacroEnabled, , , , False
End With
'code to close the original workbook to prevent accidental changes etc
Application.DisplayAlerts = False
wbkOriginal.Close
Application.DisplayAlerts = True
End Sub

Related

Resizing OLEobject custom icon

I have code to insert pdf invoice copies in customer's account statement. The code is working fine. Just the custom icon size is not as per the defined 15x51 (HxW). Please suggest how the code can resize the icon file to fit in this 15x51 box (the size of cells in column M as in below picture)? I am using a 16x16 icon file.
Here is the current result.
Sub Insert_PDF_File()
Application.ScreenUpdating = False
Dim cell As Range
' loop each cell in column A
For Each cell In Range("A10:A" & Range("A" & Rows.Count).End(xlUp).Row)
' make sure the cell is NOT empty before doing any work
If Not IsEmpty(cell) Then
' create and insert a new OleObject based on the path
Dim ol As OLEObject
' ActiveWorkbook.path & "\" & cell & ".pdf" will make the filename
Set ol = ActiveSheet.OLEObjects.Add( _
Filename:="C:\Invoices\Renamed" & "\" & cell & ".pdf", _
Link:=False, _
DisplayAsIcon:=True, _
IconFileName:="C:\Users\pvishwas\Documents\WORK\Macros\PDF.ico", _
IconIndex:=0, _
Height:=15, Width:=51, IconLabel:="Open")
' align the OleObject with Column D - (0 rows, 3 columns to the right from column A)
With ol
.Top = cell.Offset(0, 12).Top
.Left = cell.Offset(0, 12).Left
End With
End If
Next
Application.ScreenUpdating = True
End Sub
According to me, it's due to icon size.
Please check below the code I created. It takes given size for object.
Sub AddPDF()
Dim ws As Worksheet
Dim FilePath As String
Dim x As OLEObject
Set ws = ThisWorkbook.Worksheets(1)
FilePath = "D:\certificate-of-earnings.pdf"
ws.Range("A1").Select
ws.OLEObjects.Add Filename:=FilePath, Link:=False, DisplayAsIcon:=True, Height:=15, Width:=51, IconLabel:="PDF"
End Sub

Excel VBA - Loop through folder and add certain parts of names to cells in workbook

I'm trying to perform a simple exercise - (1) merge several tabs (each from separate file) into single file ("macro-file"), (2) rename all tabs in accordance with certain cells in these tabs.
Each tab is effectively a bank statement (in different currencies), so all tabs are of the same structure. I've found a macro (I'm not a specialist in VBA, so this is more about "find and adapt" than "write by myself") to merge them all, so there is no problem with step 1.
However, when I'm trying to rename all tabs at once, I'm getting a conflict - there are three tabs relating to Escrow Account and four tabs relating to Ordinary Account, and there is an intersection in currencies between accounts (each account has USD and EUR, for example).
Currently I have the following code to rename the tabs:
Sub RenameSheet ()
Dim rs As Worksheet
For Each rs In Sheets
If rs.Index > 2 Then
rs.Name = rs.Range("D4")
End If
Next rs
End Sub
What I'm looking for is the solution for problem: if file in a given folder (same as the macro-file) contains "ESCROW", then cell value in cell "D4" in the tab merged to macro-file should be changed from "USD" (let it be a USD bank statement) to "Escrow USD".
The macro should be able to check all files in folder (this is Loop, as far as I understand) and rename respectful cells at once.
Here is the example of code I tried to write-down (unsucessfully though):
Sub RenameSheet ()
Dim fName As String, wb As Workbook, rs As Worksheet
For Each rs In Sheets
If rs.Index > 2 Then
Const myPath As String = "C:\Users\my folder"
If Right(myPath, 1) <> "\" Then fPath = myPath & "\"
fName = Dir(fPath & "*Full*.xlsx*")
v = "ESCROW"
Do Until fName <> ""
If InStr(1, fName, v) > 0 Then
rs.Name = "ESCROW" + rs.Range("D4")
Else
rs.Name = rs.Range("D4")
End If
Loop
End If
Next rs
End Sub
If any of you could help me somehow, I will be grateful.
Any questions are welcome (I understand my language can be a bit tricky).
UPDATE. Current code for tabs merging is below (again, that's not mine, only googled it and inserted to my file, works perfectly):
Sub MergeExcelFiles()
Dim fnameList, fnameCurFile As Variant
Dim countFiles, countSheets As Integer
Dim wksCurSheet As Worksheet
Dim wbkCurBook, wbkSrcBook As Workbook
fnameList = Application.GetOpenFilename(FileFilter:="Microsoft Excel Workbooks (*.xls;*.xlsx;*.xlsm),*.xls;*.xlsx;*.xlsm", Title:="Choose Excel files to merge", MultiSelect:=True)
If (vbBoolean <> VarType(fnameList)) Then
If (UBound(fnameList) > 0) Then
countFiles = 0
countSheets = 0
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Set wbkCurBook = ActiveWorkbook
For Each fnameCurFile In fnameList
countFiles = countFiles + 1
Set wbkSrcBook = Workbooks.Open(FileName:=fnameCurFile)
For Each wksCurSheet In wbkSrcBook.Sheets
countSheets = countSheets + 1
wksCurSheet.Copyafter:=wbkCurBook.Sheets(wbkCurBook.Sheets.Count)
Next
wbkSrcBook.Close SaveChanges:=False
Next
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
MsgBox "Procesed " & countFiles & " files" & vbCrLf & "Merged " & countSheets & " worksheets", Title:="Merge Excel files"
End If
Else
MsgBox "No files selected", Title:="Merge Excel files"
End If
End Sub
There are a few things here and there that I changed before getting to the point:
Reordered and renamed some variables for (hopefully) simplicity
Changed the filter on documents to just *.xl* and added a secondary file filter later with Instr(file, ".xl")
Utilized the With statement for changing the Application settings
But, the important new bit comes in during the loop on each sheet in the source workbook. It does the checks that you used in the initial code - checking if index > 2 and whether "ESCROW" is in the filename - then changes the name accordingly via a With statement.
Sub MergeExcelFiles()
Dim fnameList, fnameCurFile As Variant
Dim wbkDestBook, wbkCurSrcBook As Workbook
Dim countFiles, countSheets As Long
Dim wksCurSheet As Worksheet
fnameList = Application.GetOpenFilename( _
FileFilter:="Microsoft Excel Workbooks (*.xl*),*.xl*", _
Title:="Choose Excel files to merge", _
MultiSelect:=True)
If (vbBoolean <> VarType(fnameList)) Then
If (UBound(fnameList) > 0) Then
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
End With
Set wbkDestBook = ActiveWorkbook
For Each fnameCurFile In fnameList
If InStr(LCase$(fnameCurFile), ".xl") > 0 Then 'second file filter 'prevents e.g. shortcuts (.html files) that can get this far
Set wbkCurSrcBook = Workbooks.Open(filename:=fnameCurFile)
For Each wksCurSheet In wbkCurSrcBook.Sheets
wksCurSheet.copy after:=wbkDestBook.Sheets(wbkDestBook.Sheets.count)
'renaming here
If wbkDestBook.Sheets.count > 2 Then
With wbkDestBook.Sheets(wbkDestBook.Sheets.count)
If InStr(UCase$(fnameCurFile), "ESCROW") Then
.Name = "ESCROW " & .Range("D4").Value2
Else
.Name = .Range("D4").Value2
End If
End With
End If
'end of renaming
countSheets = countSheets + 1
Next
wbkCurSrcBook.Close SaveChanges:=False
countFiles = countFiles + 1
End If
Next
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End With
MsgBox "Procesed " & countFiles & " files." & vbCrLf & "Merged " & countSheets & " worksheets.", Title:="Merge Excel files"
End If
Else
MsgBox "No files selected", Title:="Merge Excel files"
End If
End Sub

Taking info from closed workbook that has variable name

I am wondering if there is a way to not have to open a workbook to get the information from it. The issue is I am having the user select the file first because the name changes. So I am using Application.GetOpenFilename. Once they select it, since it doesn't actually open, I am trying to just grab some cells from there and copy them over. I have some other cells using vlookups referencing a workbook in the same way but this seems different or won't work. Here is the code:
Dim Window3 As String
Dim x As String
Dim lNewBracketLocation As Long
Dim shtName As String
' Prompt
strPrompt = "Please select the last 'HC Report' located in" & vbCrLf & _
"'C:\file\file\'" & vbCrLf & _
"before the dates of this Report." & vbCrLf & _
"This will be used to find the Interns that are currently working." & vbCrLf & _
"For example, if the date of this report is 9-8-17, you would want to use the 'August 2017.xlsx.' report."
' Dialog's Title
strTitle = "Latest Report"
'Display MessageBox
iRet = MsgBox(strPrompt, vbOK, strTitle)
Window3 = Application.GetOpenFilename( _
FileFilter:="Excel Files (*.xls*),*.xls*", _
Title:="Choose previous quarter's file", MultiSelect:=False)
MsgBox "You selected " & Window3
'below is some extra code from where I used this same startegy for VLOOKUP.
'Not sure if this "x" variable will be needed.
lNewBracketLocation = InStrRev(Window2, Application.PathSeparator)
'Edit the string to suit the VLOOKUP formula - insert "["
x = Left$(Window2, lNewBracketLocation) & "[" & Right$(Window2, Len(Window2) - lNewBracketLocation)
Dim wb3 As Workbook
'I want to do all of this WITHOUT opening this next file. Is that possible?
' If I open this file it works. but I am trying to do it without opening.
'Because it takes a minute
'Set wb3 = Workbooks.Open(Window3)
shtName = wb3.Worksheets("Team Members").name
'*******RIGHT here IS WHERE IT ERRORS******************
'Run-time error '91':
'Object variable or With block variable not set
Stop
wb3.Sheets(shtName).Select
ActiveSheet.Range("$A$1:$P$2769").autofilter Field:=1, Criteria1:="Interns"
Range("A2768").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.COPY
This is some other code I have that takes the vlookup without actually opening the other file. Can I do kind of the same thing? I can't get it to work.
Dim Window2 As String
Dim x As String
Dim lNewBracketLocation As Long
Window2 = Application.GetOpenFilename( _
FileFilter:="Excel Files (*.xls*),*.xls*", _
Title:="Choose previous quarter's file", MultiSelect:=False)
MsgBox "You selected " & Window2
'Find the last instance in the string of the path separator "\"
lNewBracketLocation = InStrRev(Window2, Application.PathSeparator)
'Edit the string to suit the VLOOKUP formula - insert "["
x = Left$(Window2, lNewBracketLocation) & "[" & Right$(Window2, Len(Window2) - lNewBracketLocation)
shtName = ActiveWorkbook.Worksheets(1).name
Stop
MainWindow.Activate
Columns("B:B").Select
Selection.Delete Shift:=xlToLeft
Range("AI2").FormulaR1C1 = "=VLOOKUP(RC2,'" & x & "]shtName'!R3C2:R9694C49, 23, FALSE)"
Range("AJ2").FormulaR1C1 = "=VLOOKUP(RC2,'" & x & "]shtName'!R3C2:R9694C49, 19, FALSE)"
Range("AK2").FormulaR1C1 = "=VLOOKUP(RC2,'" & x & "]shtName'!R3C2:R9694C49, 20, FALSE)"
Range("AL2").FormulaR1C1 = "=VLOOKUP(RC36,'" & x & "]shtName'!R3C2:R9694C49, 23, FALSE)"
It's impossible to copy cells across from a closed workbook. The vlookups are a different story as Excel caches a copy of the result to display when the external workbook is closed.
Just like what you're trying to do, i.e., you need to have the external file opened once to grab the data. With vlookup it's when the formula is typed/pasted into the sheet. At that time the external workbook must either be open or Excel opens it behind the scenes when you select the file from the Update Values:Book1.xlsm file selection dialog. With your code, it's when you want to grab the data. You must open it for you to cache the data yourself.
However you can solve the time issue by using this:
Application.Calculation = xlCalculationManual
Set wb3 = Workbooks.Open(Window3)
and then after you close the workbook, this:
Application.Calculation = xlCalculationAutomatic

Save excel worksheet to specific folder and filename based on same cell

I am trying to save a copy of a worksheet to a specific folder based on cell B8 and name the .xlsx file based on the cell range B8 too.
For example, a user first creates a new folder named "test1", & then enters this folder name/text into cell "B8". He/she will activate the macro after completing their work on the worksheet, & it will save a copy to the folder named "test1" and name the .xlsx file as "test1". (So the .xlsx file will be named as "testfolder1" and the folder where it is stored is also called "test1")
I am using the following code to save a copy of the worksheet to a folder. Just can't figure out how to include the cell B8 into the SaveAs line. Too new with VB to figure it out.
Sub SaveForm()
exampleForm = Range("B8").Value
Application.ScreenUpdating = False
Application.DisplayAlerts = False
ActiveSheet.Copy
With ActiveWorkbook.ActiveSheet
.Range("42:" & Rows.Count).EntireRow.Delete xlShiftDown
.Range(.Cells(1, "J"), .Cells(1, Columns.Count)).EntireColumn.Delete xlToRight
.Parent.SaveAs "C:\Users\JohnSmith\Desktop\ExtractedWorksheet\" & exampleForm & ".xlsx"
.Parent.Close False
End With
End Sub
Appreciate any input and hopefully my ending goal is understandable.
-Thanks!
I think this is what you're after, give it a try:
Sub SaveForm()
Static Path as string
Static FileName as string
if len(Path) = 0 then
Path = Range("B8")
if right(Path,1) <> "\" then
'make sure the path is "\" terminated
Path = Path & "\"
End if
else
FileName = Range("B8")
'Application.ScreenUpdating = False
Application.DisplayAlerts = False
ActiveSheet.Copy 'not sure why you're doing this, but do so if it makes sense elsewhere in your code
With ActiveWorkbook.ActiveSheet
.Range("42:" & Rows.Count).EntireRow.Delete xlShiftDown
.Range(.Cells(1, "J"), .Cells(1, Columns.Count)).EntireColumn.Delete xlToRight
.Parent.SaveAs "C:\Users\JohnSmith\Desktop\ExtractedWorksheet\" & Path & _
FileName & ".xlsx"
.Parent.Close False
End With
Path = ""
FileName = ""
End if
End Sub
If you call this code from your worksheet_OnChange event, then when cell B8 is updated, it will:
check to see if you have a Path stored. If not, assume this is the Path
If you have a Path already, assume this is the FileName and save it.
Leave the 'Application.ScreenUpdating` commented out until everything is working OK, then put it back in. Makes figuring out what's going on much easier.
UPDATE based on your latest comment on OP:
Sub SaveForm()
'Application.ScreenUpdating = False
Application.DisplayAlerts = False
ActiveSheet.Copy 'not sure why you're doing this, but do so if it makes sense elsewhere in your code
With ActiveWorkbook.ActiveSheet
.Range("42:" & Rows.Count).EntireRow.Delete xlShiftDown
.Range(.Cells(1, "J"), .Cells(1, Columns.Count)).EntireColumn.Delete xlToRight
.Parent.SaveAs "C:\Users\JohnSmith\Desktop\ExtractedWorksheet\" & _
Range("B8") & "\" & FileName & ".xlsx"
.Parent.Close False
End With
Path = ""
FileName = ""
End Sub
Here is one that I have created for a project that I worked on.
I first named a cell (through Excel user interface-formula-name
manager-define name) and called it prform_prnumber.
I passed the value in that to a variant variable in vba and called it prnumber.
I then used that variable as name in the exporttopdf method.
I kept the path as that of the workbook.
This code will run (once the button is clicked) in the active worksheet:
Sub exporttopdf()
Dim prnumber As Variant
Set prnumber = ActiveWorkbook.Names("prform_prnumber").RefersToRange
ActiveSheet.ExportAsFixedFormat xlTypePDF, ActiveWorkbook.Path & "/" & filesavename & ".pdf", , , False
End Sub

How to exclude 1 sheet from my save to pdf VBA macro

I have a VBA code that works well, apart from the fact that i don't know how to exclude one sheet from saving to the PDF. I would like the exclude the sheet named 'Control' from being included in the export and save to PDF. Any ideas how or where i should add this?
Thanks
Sub CreatePDF()
Dim saveAsName As String
Dim WhereTo As String
Dim sFileName As String
Dim ws As Worksheet
Dim myrange
' Retrieve information from Control sheet
Sheets("Control").Activate
Range("C4").Activate
periodName = ActiveCell.Value
Range("C5").Activate
saveAsName = ActiveCell.Value
Range("C6").Activate
WhereTo = ActiveCell.Value
Set myrange = Worksheets("Control").Range("range_sheetProperties")
' Check if Stamp-field has any value at all
' if not, add the current date.
If Stamp = "" Then Stamp = Date
' Assemble the filename
sFileName = WhereTo & saveAsName & " (" & Format(CDate(Date), "DD-MMM-YYYY") & ").pdf"
' Format all sheets as landsape, autofit to 1 page and provide header
For Each ws In ActiveWorkbook.Worksheets
With ws.PageSetup
Application.PrintCommunication = False
.Orientation = xlLandscape
.Zoom = False
.FitToPagesWide = 1
.CenterHorizontally = True
.ScaleWithDocHeaderFooter = False
.AlignMarginsHeaderFooter = False
.HeaderMargin = Application.InchesToPoints(0.31496062992126)
Application.PrintCommunication = True
DisplayHeader = Application.VLookup(ws.Name, myrange, 2, False)
If Not IsError(DisplayHeader) Then
.LeftHeader = "&L &""Arial,Bold""&11&K00-048DIVA: " & DisplayHeader
Else: .LeftHeader = "&L &""Arial,Bold""&11&KFF0000WORKSHEET NOT DEFINED IN CONTROL SHEET "
End If
.CenterHeader = "&C &""Arial,Bold""&11&K00-048" & periodName
End With
Next
' Save the File as PDF
ActiveWorkbook.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
sFileName, Quality _
:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas:=False, _
OpenAfterPublish:=True
MsgBox "PDF document has been created and saved to : " & sFileName
' Make sure we open the Control sheet upon Exit
Sheets("Control").Activate
End Sub
You could hide the worksheet at the beginning of the code and then make it visible again at the end.
TESTED:
' Retrieve information from Control sheet
Sheets("Control").Visible = False
'YOUR PDF CREATION CODE
Sheets("Control").Visible = True
Sheets("Control").Activate
I ran into the same problem and just hid the sheet during the export function, then I brought it back... Here is the code:
'Hide the log sheet to exclude from export
ActiveWorkbook.Sheets("Log").Visible = xlSheetHidden
ActiveWorkbook.ExportAsFixedFormat Type:=xlTypePDF, FileName:=FilePath + Today + "\" + Range("H2").Value _
, Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
:=False, OpenAfterPublish:=True
'Bring back the log sheet to allow for editing
ActiveWorkbook.Sheets("Log").Visible = xlSheetVisible