I recently asked about saving an excel file with a specific name to a set location:
Getting correct default save name and save directory with spaces in VBA
I want to use this same procedure but in a somewhat different way. I tried to edit the code to make it work, but I keep on have a black filename screen when I execute the code.
The file I want to save with the routine is a template which is being refreshed with new data every 4 weeks. It is a read-only file which functions as a source template and after updating the data, I has to be saved on a different location to keep the original source file save from errors/unwanted modification.
When refreshing, the template opens a file which contains the refresh script named "refresh_segment_template.xlsm".
the code in the template is:
Option Explicit
Dim aantalrijen As Long
Const SheetSchaduwblad As String = "schaduwblad"
-------
Sub vernieuwalles()
Dim myTemplate As String: myTemplate = ActiveWorkbook.Name
Dim myTool As String: myTool = "refresh_segment_template.xlsm"
Application.ScreenUpdating = False
Workbooks.Open GetPath & myTool
Application.Run myTool & "!vernieuwalles", myTemplate
Call Windows(myTool).Close(False)
Application.ScreenUpdating = True
End Sub
Private Function GetPath() As String
Dim myPosition As Integer
Dim myPath As String: myPath = ActiveWorkbook.Path
myPosition = InStr(StrReverse(myPath), "\") - 1
myPosition = Len(myPath) - myPosition
GetPath = Mid(myPath, 1, myPosition - 1) & "\XLAM\"
End Function
the code in the refresh_segment_template is:
Option Explicit
Dim aantalrijen As Long
Const SheetSchaduwblad As String = "schaduwblad"
------------------
Sub vernieuwalles(mytemplate As String)
Windows(mytemplate).Activate
On Error GoTo Err_
Application.StatusBar = "Bezig met vernieuwen"
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' Call SheetOpschonen
Call datawissen
Call dataplaatsen
Call kolomtitels
Call toevoegen
Call maaktabel
Call refreshpivots
Exit_:
Application.StatusBar = ""
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Exit Sub
Err_:
Call MsgBox(Err.Number & vbCrLf & Err.Description)
Resume Exit_
Application.Calculation = xlCalculationAutomatic
End Sub
-------------
Sub refreshpivots()
Dim workbook_Name As Variant
Dim location As String
Dim filename As String
filename = "M:\Commercie\Marktdata\IRi\Segment Ontwikkeling\" & ActiveWorkbook.Name
ActiveWorkbook.RefreshAll
workbook_Name = Application.GetSaveAsFilename(fileFilter:="Excel binary sheet (*.xlsb), *.xlsb", InitialFileName:="M:\Commercie\Marktdata\IRi\Segment Ontwikkeling\")
If workbook_Name <> False Then
ActiveWorkbook.SaveAs filename:=filename, WriteResPassword:="TM", FileFormat:=50
End If
End Sub
I am now wondering how I can make the last script to use the filename of the template and save it on the give location in the script (i.e. M:\Commercie\Marktdata\IRi\Segment Ontwikkeling).
When I execute the code above, I get a 'save as' screen, but with no filename given, only the set directory is correct.
The refresh_segment_template is a .xlsm file. The template is a .xlsb file.
Related
I am trying to run a PowerPoint Macro through Excel VBA, I used to be able to run a macro on a powerpoint file with ease but I am having trouble passing a parameter in excel.
Sub Test()
Dim arr(1 To 1), macname As String, objPP As Object, PPTFilePath As String, ObjPPFile As Object,
PPtFileName As String
PPTFileName ="Report.pptm"
PPTFilePath ThisWorkbook.Path & PPTFileName
Set objPP = CreateObject("PowerPoint.Application")
objPP.Visible = True
Set objPPFile = objPP.Presentations.Open(PPTFilePath)
Application.EnableEvents = False
arr(1) = ThisWorkbook.Path
macname = "'" & PPTFileName & "'!Module3.UpdateSpecificLinks"
objPP.Run macname, arr
objPPFile.Save
waiting (3)
Application.EnableEvents = True
End Sub
I get an error on objPP.Run macname, arr , it is: Run-time error '-2147188160 (80048240)': Application.Run :Invalid request. Sub or Function not defined.
How do I properly Pass a parameter to the powerpoint macro: Sub UpdateSpecificLinks(LNK as String)
If your SubUpdateSpecificLinks is e.g. in a private module, the call to it will fail; it must be public.
I think this is the problem, though:
macname = "'" & PPTFileName & "'!Module3.UpdateSpecificLinks"
Try this instead:
macname = PPTFileName & "!Module3.UpdateSpecificLinks"
A couple of examples, calling from a PPTM file to another (closed) PPTM file:
Here are the calling macros:
Sub TestWithString()
Dim sFileName As String
Dim oPres As Presentation
sFileName = "C:\temp\runme.pptm"
Set oPres = Presentations.Open(sFileName, , , False)
Application.Run "C:\temp\RunMe.pptm!RunMe", "This is the passed parameter"
oPres.Close
End Sub
Sub TestWithArray()
Dim sFileName As String
Dim oPres As Presentation
Dim aStrings(1 To 3) As String
sFileName = "C:\temp\runme.pptm"
Set oPres = Presentations.Open(sFileName, , , False)
aStrings(1) = "String 1"
aStrings(2) = "String 2"
aStrings(3) = "String 3"
Application.Run "C:\temp\RunMe.pptm!HowAboutAnArray", aStrings
oPres.Close
End Sub
And here are the macros they call:
Sub RunMe(sMsg As String)
MsgBox "You said " & sMsg
End Sub
Sub HowAboutAnArray(vParm As Variant)
Dim x As Long
For x = 1 To ubound(vParm)
MsgBox vParm(x)
Next
End Sub
I have 1 external xlsm file that contains the macro code I need to perform operations for several templates. This is the actual process how I would like to have it in short:
'Template' is opened by user. User clicks 'refresh' button
'mytool' is opened and performs several operations in 'template'
after performing operations 'mytool' is closed again and templates is saved
user works in template with updated data.
I now want to change this tool a bit so it not only performs operations on the target workbook, but firstly, copies the needed data from another external workbook. I have been trying and searching to find code to have this done, but I am struggling with it to get it right.
'Template' is opened by user. User clicks 'refresh' button
'mytool' is opened and performs several operations in 'template' including opening the raw data file and copying the data in the file to 'template'
after performing operations 'mytool' is closed again and templates is saved
user works in template with updated data.
edit: own solution added to question on the bottom of this question.
I have this code to make the external tool act/work in the target workbook:
Sub vernieuwalles(mytemplate As String)
Windows(mytemplate).Activate
In the target workbook, I have this code:
Sub vernieuwalles()
Dim myTemplate As String: myTemplate = ActiveWorkbook.Name
Dim myTool As String: myTool = "refresh_base_incrementals.xlsm"
Application.ScreenUpdating = False
Workbooks.Open GetPath & myTool
Application.Run myTool & "!vernieuwalles", myTemplate
Call Windows(myTool).Close(False)
Application.ScreenUpdating = True
End Sub
Private Function GetPath() As String
Dim myPosition As Integer
Dim myPath As String: myPath = ActiveWorkbook.Path
myPosition = InStr(StrReverse(myPath), "\") - 1
myPosition = Len(myPath) - myPosition
GetPath = Mid(myPath, 1, myPosition - 1) & "\XLAM\"
End Function
I want the tool to open another excel file which is located in a seperate directory. This is the directory structure I use for this:
location target workbook:
\Promo reports\test\
this is the location for the tool:
\promo reports\xlam\
this is the location for the external workbook:
\Promo reports\test\data files\
I was already busy with adjusting existing code to have the correct location in it:
Sub import_data()
Dim directory As String, fileName As String, sheet As Worksheet, total As Integer
Workbooks.Open GetPath & fileName
fileName = Mid(mytemplate,18,Len(mytemplate) - 4
End Sub
Private Function GetPath() As String
Dim myPosition As Integer
Dim myPath As String: myPath = ActiveWorkbook.Path
myPosition = InStr(StrReverse(myPath), "\") - 1
myPosition = Len(myPath) - myPosition
GetPath = Mid(myPath, 1, myPosition - 1) & "\test\data files\"
End Function
But then I got stock. I want the data from 3 sheets having copied to those some sheets (they already exist) in the target workbook.
There are 3 sheets: Food-Drug, ASW A, ASW P.
The external workbook is a data file which filename will be consequently the same as the templates name but shorts. for example:
the template name is promo rapportage prostaat.xlsb
the datafile name will be prostaat.xlsb
I want the tool to use the name of the template to get the right filename to open in the data files directory.
How can I add these operations to "mytool"?
edit:
I now changed the code(s) to this:
in the target workbook:
Option Explicit
Sub vernieuwalles()
Dim mytemplate As String: mytemplate = ActiveWorkbook.Name
Dim myTool As String: myTool = "refresh_base_incrementals.xlsm"
Dim myData As String: myData = Mid(ActiveWorkbook.Name, 18, Len(ActiveWorkbook.Name) - 4)
Application.ScreenUpdating = False
Workbooks.Open GetPath & myTool
Workbooks.Open GetPath2 & myData
Application.Run myTool & "!vernieuwalles", mytemplate
Call Windows(myTool).Close(False)
Application.ScreenUpdating = True
End Sub
Private Function GetPath() As String
Dim myPosition As Integer
Dim myPath As String: myPath = ActiveWorkbook.Path
myPosition = InStr(StrReverse(myPath), "\") - 1
myPosition = Len(myPath) - myPosition
GetPath = Mid(myPath, 1, myPosition - 1) & "\XLAM\"
End Function
Private Function GetPath2() As String
Dim myPosition As Integer
Dim myPath As String: myPath = ActiveWorkbook.Path
myPosition = InStr(StrReverse(myPath), "\") - 1
myPosition = Len(myPath) - myPosition
GetPath2 = Mid(myPath, 1, myPosition - 1) & "\test\data files\"
End Function
And in the external script file (mytool):
Sub importdata()
Dim mytemplate As String: mytemplate = ActiveWorkbook.name
Dim myData As String: myData = Mid(ActiveWorkbook.name, 18, Len(ActiveWorkbook.name) - 4)
Dim sheetnames As Variant, i As Integer
sheetnames = Array("food-drug", "ASW A-merk", "ASW PL")
For i = LBound(sheetnames) To UBound(sheetnames)
With Workbooks(myData).Sheets(sheetnames(i))
aantalrijen = .Range("A1", .Range("A1").End(xlDown)).Cells.Count - 1
.Range(.Cells(1, "A"), .Cells(aantalrijen, "DO")).Copy _
Workbooks(mytemplate).Sheets(sheetnames(i)).Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
End With
Next i
End Sub
I tested this with a template called 'promo rapportage prostaat.xlsb' and it perfectly opens the file prostaat.xlsb and copies the data on the 3 worksheets in this file to the worksheets in the target workbook.
I have an excel template which is recommended to open as read-only on opening to users (I have the password to open file to be able to change/edit the file).
I have a vba script which saves the read-only opened file.
When I save the file the normal way (menu > save as > choose file > save) excel returns a message telling me the file cannot saved because it is opened as read-only.
When I use the script, a popup shows me the desired directory with the proper filename, and saving is possible (so opened as read-only, it still can be saved with the same filename). No errors at all.
But when I look in the directory now, most of the files I have updated and saved do not have an updated 'last edited date/time'. And when I open the file, all changes I have made are not in the file anymore.
Is it possible that VBA says it has saved the file with the same filename, although the file was opened as read-only, but in fact did not save anything?
here is the save-as code:
Sub vernieuwalles(mytemplate As String)
Dim workbook_Name As Variant
Windows(mytemplate).Activate
On Error GoTo Err_
MsgBox ("Bezig met vernieuwen")
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' Call SheetOpschonen
Call datawissen
Call dataplaatsen
Call kolomtitels
Call toevoegen
Call maaktabel
Call refreshpivots
workbook_Name = Application.GetSaveAsFilename(fileFilter:="Excel binary sheet (*.xlsb), *.xlsb", InitialFileName:="M:\Commercie\Marktdata\IRi\Segment ontwikkeling\")
MsgBox workbook_Name
If workbook_Name <> False Then
ActiveWorkbook.SaveAs Filename:=workbook_Name, FileFormat:=50
End If
Exit_:
Application.StatusBar = ""
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Exit Sub
Err_:
Call MsgBox(Err.Number & vbCrLf & Err.Description)
Resume Exit_
Application.Calculation = xlCalculationAutomatic
End Sub
it seems to work, but as I found out, it does not work when the file is opened as read-only, although I looks like the file is saved and can overwrite the original file while being opened as read-only.
update 2019-04-11 10:00 AM:
with the suggestion from ZACK I adjusted my save as code to:
Sub vernieuwalles(mytemplate As String)
Dim workbook_Name As Variant
Windows(mytemplate).Activate
On Error GoTo Err_
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' Call SheetOpschonen
Call datawissen
Call dataplaatsen
Call kolomtitels
Call toevoegen
Call maaktabel
Call refreshpivots
If ActiveWorkbook.ReadOnly = True Then ActiveWorkbook.ChangeFileAccess Mode:=xlReadWrite
workbook_Name = Application.GetSaveAsFilename(fileFilter:="Excel binary sheet (*.xlsb), *.xlsb", InitialFileName:="M:\Commercie\Marktdata\IRi\Segment ontwikkeling\")
If workbook_Name <> False Then ActiveWorkbook.SaveAs Filename:=workbook_Name, FileFormat:=50
ActiveWorkbook.ChangeFileAccess Mode:=xlReadOnly
Exit_:
Application.StatusBar = ""
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Exit Sub
Err_:
Call MsgBox(Err.Number & vbCrLf & Err.Description)
Resume Exit_
Application.Calculation = xlCalculationAutomatic
End Sub
opening a read-only file and saving it while overwriting the original read-only file works. Except for that I know have to enter the filename again. While if before uses the original filename, there is no filename shown in the save as popup screen anymore.
update 2 2019-04-11 10:31 AM:
I had some additional "save as code" for getting the right filename which I used before (was in the original post). I added this code to my main macro and tested if it works. Now the file access is changed correctly, the save as popup shows the correct filename in the right directory and the file is saved.
Conclusion: case closed, question answered!
Here is how it works (for me):
Sub vernieuwalles(mytemplate As String)
Dim workbook_Name As Variant
Dim workbookdirectory As String
Dim activewb As String
Windows(mytemplate).Activate
On Error GoTo Err_
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' Call SheetOpschonen
Call datawissen
Call dataplaatsen
Call kolomtitels
Call toevoegen
Call maaktabel
Call refreshpivots
If ActiveWorkbook.ReadOnly = True Then ActiveWorkbook.ChangeFileAccess Mode:=xlReadWrite
activewb = Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 5)
workbookdirectory = "M:\Commercie\Marktdata\IRi\Segment Ontwikkeling\"
workbook_Name = Application.GetSaveAsFilename(fileFilter:="Excel binary sheet (*.xlsb), *.xlsb", InitialFileName:=workbookdirectory & activewb)
If workbook_Name <> False Then ActiveWorkbook.SaveAs Filename:=workbook_Name, FileFormat:=50
ActiveWorkbook.ChangeFileAccess Mode:=xlReadOnly
Exit_:
Application.StatusBar = ""
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Exit Sub
Err_:
Call MsgBox(Err.Number & vbCrLf & Err.Description)
Resume Exit_
Application.Calculation = xlCalculationAutomatic
End Sub
One other solution you can try is this, which is what Zac was talking about. It will change the access of the active workbook so you can run your code then change it back to read only.
Sub saveas()
Dim workbook_Name As Variant
Dim location As String
Dim workbookdirectory As String
Dim activewb As String
ActiveWorkbook.ChangeFileAccess Mode:=xlReadWrite
activewb = Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 5)
workbookdirectory = "M:\Commercie\Marktdata\IRi\Segment Ontwikkeling\"
workbook_Name = Application.GetSaveAsFilename(fileFilter:="Excel binary sheet (*.xlsb), *.xlsb", InitialFileName:=workbookdirectory & activewb)
If workbook_Name = False Then ActiveWorkbook.saveas Filename:=activewb, FileFormat:=50
ActiveWorkbook.ChangeFileAccess Mode:=xlReadOnly
End Sub
I have a script which opens an external file to execute a script and after finishing the script, it saves as an xlsb file. The code worked perfectly for saving from xlsb file to xlsb file. But because I want to have some security for the original file, I want the original xlsb file to be a xltm file. I adapted the save as script to it and tested it as a separate routine in the file itself. It works perfectly.
Now I added the routine to the external script file, but when I execute the script then, Excel freezes and no 'save as' screen appears at all.
I expect the external script to have some other external reference to work properly but I cannot figure out how to adjust my script to this.
This is the code of the original file:
Option Explicit
Sub vernieuwalles()
Dim myTemplate As String: myTemplate = ActiveWorkbook.Name
Dim myTool As String: myTool = "refresh_segment_template.xlsm"
Application.ScreenUpdating = False
Workbooks.Open GetPath & myTool
Application.Run myTool & "!vernieuwalles", myTemplate
Call Windows(myTool).Close(False)
Application.ScreenUpdating = True
End Sub
Private Function GetPath() As String
Dim myPosition As Integer
Dim myPath As String: myPath = ActiveWorkbook.Path
myPosition = InStr(StrReverse(myPath), "\") - 1
myPosition = Len(myPath) - myPosition
GetPath = Mid(myPath, 1, myPosition - 1) & "\XLAM\"
End Function
It refers to the external script file to be opened and executed.
The external file has this script (I only pasted the save as part of the script):
Option Explicit
Dim aantalrijen As Long
Const SheetSchaduwblad As String = "schaduwblad"
Sub vernieuwalles(mytemplate As String)
Windows(mytemplate).Activate
On Error GoTo Err_
Application.StatusBar = "Bezig met vernieuwen"
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' Call SheetOpschonen
Call datawissen
Call dataplaatsen
Call kolomtitels
Call toevoegen
Call maaktabel
Call refreshpivots
Exit_:
Application.StatusBar = ""
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Exit Sub
Err_:
Call MsgBox(Err.Number & vbCrLf & Err.Description)
Resume Exit_
Application.Calculation = xlCalculationAutomatic
End Sub
Sub refreshpivots()
Dim workbook_Name As Variant
Dim location As String
Dim workbookdirectory As String
Dim activewb As String
ActiveWorkbook.RefreshAll
activewb = Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 5)
workbookdirectory = "M:\Commercie\Marktdata\IRi\Segment Ontwikkeling\"
workbook_Name = Application.GetSaveAsFilename(fileFilter:="Excel binary sheet (*.xlsb), *.xlsb", InitialFileName:=workbookdirectory & activewb)
If workbook_Name = False Then
ActiveWorkbook.SaveAs filename:=activewb, FileFormat:=50
End If
But when I execute the script from the original file, excel freezes as pointed out. What should be changed for this code to be working with the external file and the save from xltm to xlsb script?
As pointed out: the save as script is the only thing that has changed in the script and the xlsb to xltm extension-change is the only thing that has changed in the original file.
How do I save each sheet in an Excel workbook to separate CSV files with a macro?
I have an excel with multiple sheets and I was looking for a macro that will save each sheet to a separate CSV (comma separated file). Excel will not allow you to save all sheets to different CSV files.
#AlexDuggleby: you don't need to copy the worksheets, you can save them directly. e.g.:
Public Sub SaveWorksheetsAsCsv()
Dim WS As Excel.Worksheet
Dim SaveToDirectory As String
SaveToDirectory = "C:\"
For Each WS In ThisWorkbook.Worksheets
WS.SaveAs SaveToDirectory & WS.Name, xlCSV
Next
End Sub
Only potential problem is that that leaves your workbook saved as the last csv file. If you need to keep the original workbook you will need to SaveAs it.
Here is one that will give you a visual file chooser to pick the folder you want to save the files to and also lets you choose the CSV delimiter (I use pipes '|' because my fields contain commas and I don't want to deal with quotes):
' ---------------------- Directory Choosing Helper Functions -----------------------
' Excel and VBA do not provide any convenient directory chooser or file chooser
' dialogs, but these functions will provide a reference to a system DLL
' with the necessary capabilities
Private Type BROWSEINFO ' used by the function GetFolderName
hOwner As Long
pidlRoot As Long
pszDisplayName As String
lpszTitle As String
ulFlags As Long
lpfn As Long
lParam As Long
iImage As Long
End Type
Private Declare Function SHGetPathFromIDList Lib "shell32.dll" _
Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long
Private Declare Function SHBrowseForFolder Lib "shell32.dll" _
Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long
Function GetFolderName(Msg As String) As String
' returns the name of the folder selected by the user
Dim bInfo As BROWSEINFO, path As String, r As Long
Dim X As Long, pos As Integer
bInfo.pidlRoot = 0& ' Root folder = Desktop
If IsMissing(Msg) Then
bInfo.lpszTitle = "Select a folder."
' the dialog title
Else
bInfo.lpszTitle = Msg ' the dialog title
End If
bInfo.ulFlags = &H1 ' Type of directory to return
X = SHBrowseForFolder(bInfo) ' display the dialog
' Parse the result
path = Space$(512)
r = SHGetPathFromIDList(ByVal X, ByVal path)
If r Then
pos = InStr(path, Chr$(0))
GetFolderName = Left(path, pos - 1)
Else
GetFolderName = ""
End If
End Function
'---------------------- END Directory Chooser Helper Functions ----------------------
Public Sub DoTheExport()
Dim FName As Variant
Dim Sep As String
Dim wsSheet As Worksheet
Dim nFileNum As Integer
Dim csvPath As String
Sep = InputBox("Enter a single delimiter character (e.g., comma or semi-colon)", _
"Export To Text File")
'csvPath = InputBox("Enter the full path to export CSV files to: ")
csvPath = GetFolderName("Choose the folder to export CSV files to:")
If csvPath = "" Then
MsgBox ("You didn't choose an export directory. Nothing will be exported.")
Exit Sub
End If
For Each wsSheet In Worksheets
wsSheet.Activate
nFileNum = FreeFile
Open csvPath & "\" & _
wsSheet.Name & ".csv" For Output As #nFileNum
ExportToTextFile CStr(nFileNum), Sep, False
Close nFileNum
Next wsSheet
End Sub
Public Sub ExportToTextFile(nFileNum As Integer, _
Sep As String, SelectionOnly As Boolean)
Dim WholeLine As String
Dim RowNdx As Long
Dim ColNdx As Integer
Dim StartRow As Long
Dim EndRow As Long
Dim StartCol As Integer
Dim EndCol As Integer
Dim CellValue As String
Application.ScreenUpdating = False
On Error GoTo EndMacro:
If SelectionOnly = True Then
With Selection
StartRow = .Cells(1).Row
StartCol = .Cells(1).Column
EndRow = .Cells(.Cells.Count).Row
EndCol = .Cells(.Cells.Count).Column
End With
Else
With ActiveSheet.UsedRange
StartRow = .Cells(1).Row
StartCol = .Cells(1).Column
EndRow = .Cells(.Cells.Count).Row
EndCol = .Cells(.Cells.Count).Column
End With
End If
For RowNdx = StartRow To EndRow
WholeLine = ""
For ColNdx = StartCol To EndCol
If Cells(RowNdx, ColNdx).Value = "" Then
CellValue = ""
Else
CellValue = Cells(RowNdx, ColNdx).Value
End If
WholeLine = WholeLine & CellValue & Sep
Next ColNdx
WholeLine = Left(WholeLine, Len(WholeLine) - Len(Sep))
Print #nFileNum, WholeLine
Next RowNdx
EndMacro:
On Error GoTo 0
Application.ScreenUpdating = True
End Sub
And here's my solution should work with Excel > 2000, but tested only on 2007:
Private Sub SaveAllSheetsAsCSV()
On Error GoTo Heaven
' each sheet reference
Dim Sheet As Worksheet
' path to output to
Dim OutputPath As String
' name of each csv
Dim OutputFile As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.EnableEvents = False
' ask the user where to save
OutputPath = InputBox("Enter a directory to save to", "Save to directory", Path)
If OutputPath <> "" Then
' save for each sheet
For Each Sheet In Sheets
OutputFile = OutputPath & "\" & Sheet.Name & ".csv"
' make a copy to create a new book with this sheet
' otherwise you will always only get the first sheet
Sheet.Copy
' this copy will now become active
ActiveWorkbook.SaveAs FileName:=OutputFile, FileFormat:=xlCSV, CreateBackup:=False
ActiveWorkbook.Close
Next
End If
Finally:
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.EnableEvents = True
Exit Sub
Heaven:
MsgBox "Couldn't save all sheets to CSV." & vbCrLf & _
"Source: " & Err.Source & " " & vbCrLf & _
"Number: " & Err.Number & " " & vbCrLf & _
"Description: " & Err.Description & " " & vbCrLf
GoTo Finally
End Sub
(OT: I wonder if SO will replace some of my minor blogging)
Building on Graham's answer, the extra code saves the workbook back into it's original location in it's original format.
Public Sub SaveWorksheetsAsCsv()
Dim WS As Excel.Worksheet
Dim SaveToDirectory As String
Dim CurrentWorkbook As String
Dim CurrentFormat As Long
CurrentWorkbook = ThisWorkbook.FullName
CurrentFormat = ThisWorkbook.FileFormat
' Store current details for the workbook
SaveToDirectory = "C:\"
For Each WS In ThisWorkbook.Worksheets
WS.SaveAs SaveToDirectory & WS.Name, xlCSV
Next
Application.DisplayAlerts = False
ThisWorkbook.SaveAs Filename:=CurrentWorkbook, FileFormat:=CurrentFormat
Application.DisplayAlerts = True
' Temporarily turn alerts off to prevent the user being prompted
' about overwriting the original file.
End Sub
A small modification to answer from Alex is turning on and off of auto calculation.
Surprisingly the unmodified code was working fine with VLOOKUP but failed with OFFSET. Also turning auto calculation off speeds up the save drastically.
Public Sub SaveAllSheetsAsCSV()
On Error GoTo Heaven
' each sheet reference
Dim Sheet As Worksheet
' path to output to
Dim OutputPath As String
' name of each csv
Dim OutputFile As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.EnableEvents = False
' Save the file in current director
OutputPath = ThisWorkbook.Path
If OutputPath <> "" Then
Application.Calculation = xlCalculationManual
' save for each sheet
For Each Sheet In Sheets
OutputFile = OutputPath & Application.PathSeparator & Sheet.Name & ".csv"
' make a copy to create a new book with this sheet
' otherwise you will always only get the first sheet
Sheet.Copy
' this copy will now become active
ActiveWorkbook.SaveAs Filename:=OutputFile, FileFormat:=xlCSV, CreateBackup:=False
ActiveWorkbook.Close
Next
Application.Calculation = xlCalculationAutomatic
End If
Finally:
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.EnableEvents = True
Exit Sub
Heaven:
MsgBox "Couldn't save all sheets to CSV." & vbCrLf & _
"Source: " & Err.Source & " " & vbCrLf & _
"Number: " & Err.Number & " " & vbCrLf & _
"Description: " & Err.Description & " " & vbCrLf
GoTo Finally
End Sub
For Mac users like me, there are several gotchas:
You cannot save to any directory you want. Only few of them can receive your saved files. More info there
Here is a working script that you can copy paste in your excel for Mac:
Public Sub SaveWorksheetsAsCsv()
Dim WS As Excel.Worksheet
Dim SaveToDirectory As String
SaveToDirectory = "~/Library/Containers/com.microsoft.Excel/Data/"
For Each WS In ThisWorkbook.Worksheet
WS.SaveAs SaveToDirectory & WS.Name & ".csv", xlCSV
Next
End Sub
Use Visual Basic to loop through worksheets and save .csv files.
Open up .xlsx file in Excel.
Press option+F11
Insert → Module
Insert this into the module code:
Public Sub SaveWorksheetsAsCsv()
Dim WS As Excel.Worksheet
Dim SaveToDirectory As String
SaveToDirectory = "./"
For Each WS In ThisWorkbook.Worksheets
WS.SaveAs SaveToDirectory & WS.Name & ".csv", xlCSV
Next
End Sub
Run the module.
(i.e. Click the play button at the top and then click "Run" on the dialog, if it pops up.)
Find your .csv files in ~/Library/Containers/com.microsoft.Excel/Data.
open ~/Library/Containers/com.microsoft.Excel/Data
Close .xlsx file.
Rinse and repeat for other .xlsx files.
Please look into Von Pookie's answer, all credits to him/her.
Sub asdf()
Dim ws As Worksheet, newWb As Workbook
Application.ScreenUpdating = False
For Each ws In Sheets(Array("EID Upload", "Wages with Locals Upload", "Wages without Local Upload"))
ws.Copy
Set newWb = ActiveWorkbook
With newWb
.SaveAs ws.Name, xlCSV
.Close (False)
End With
Next ws
Application.ScreenUpdating = True
End Sub