Code to automatically save data from Excel sheet to CSV file - vba

Does there exist a code to for example save every hour the data from A1:B10 in sheet1 to a CSV file ?

Although this can be done in many different ways, this is what I'd do:
1) Add the following sub to a new file. Let's call it "auto.xlsb"
Sub SaveRangeToCSV()
Dim rng As Range
Dim originWB As Workbook
Dim originWS As Worksheet
Dim newBook As Workbook
Dim newBookWS As Worksheet
'Open the file you want to copy the range from
Set originWB = Workbooks.Open("path_to_file_that_contains_the_range_you_want_to_copy.xlsx")
Set originWS = ThisWorkbook.Sheets("name_of_the_sheet_where_the_range_is")
Set rng = originWS.Range("A1:B10")
'Add new workbook (csv file)
Workbooks.Add
Set newBook = ActiveWorkbook
Set newBookWS = newBook.Sheets(1)
'Copy range from origin to destination (csv file)
rng.Copy Destination:=newBookWS.Range("A1")
'Save csv file
newBook.SaveAs Filename:=ThisWorkbook.Path & "\output.csv"
End Sub
If you want to avoid the output.csv to be overwritten every 10 minutes, you could, for example, add current datetime to the filename like this:
'Save csv file
newBook.SaveAs Filename:=ThisWorkbook.Path & "\output_" & Replace(Replace(Replace(Now, "/", ""), ":", ""), " ", "") & ".csv"
2) Add this code to Workbook_Open Sub (click ThisWorkbook sheet in VBA IDE, and select Workbook and Open from the dropdown) in auto.xlsb, and Save:
Private Sub Workbook_Open()
Call Module1.SaveRangeToCSV
End Sub
Every time you doble-click to open the file, SaveRangeToCSV will be triggered and, hence, the csv created.
3) Automating the execution of this file really depends on your preferences and the Operating System you are working on. I'm assuming your are on Windows, so the easiest way to do it would be creating a task in Windows' Task Scheduler which runs "auto.xlsb" every 10 minutes.
I hope this helps.

Related

Get data from another excel file with not fixed worksheet name

I have a excel file that contain daily order id and I need to get some data from other excel use the order id as index. The source file contain many worksheet that means a listbox with sheet name for selection is required.
The workbook & worksheet used for data source is not fixed and will determine by user, so a listbox for user to select relevant worksheet is required
The workflow is when i call the vba at the daily excel file, a listbox with all sheet name of the source excel file will pop up for select worksheet, then the daily excel file will get data from the source excel base on the order id as index.
Now I have a vba using activeworkbook and activeworksheet to set the lookup range, but I don't think this is a good coding method. Could someone can give me some suggestion?
For the userform code if the strfile is set to an exact file the code is fine, but the source file may be change.
All source files are save in same location, the required source file name is in Range("Z1") of the daily excel file, is it possible the strfile can change base on Range("Z1")?
Please let me know if I can clarify anything for you.
Sub example()
Dim dest_wbk As Workbook
Dim dest_ws As Worksheet
Dim source_wbk As Workbook
Dim source_ws As Worksheet
Set dest_wbk = ThisWorkbook
Set dest_ws = dest_wbk.ActiveSheet
sourcefilename = Range("Z1")
UserForm1.Show
Set source_wbk = ActiveWorkbook
Set source_ws = source_wbk.ActiveSheet
sourcelastrow = source_ws.Cells(Rows.Count, 2).End(xlUp).Row
Set lookuprange = source_ws.Range("A2:E" & sourcelastrow)
dest_lastrow = dest_ws.Cells(Rows.Count, 4).End(xlUp).Row
For i = 2 To des_lastrow
ID = dest_ws.Range("D" & i)
dest_ws.Range("K" & i) = Application.VLookup(ID, lookuprange, 3, False)
dest_ws.Range("L" & i) = Application.VLookup(ID, lookuprange, 4, False)
Next i
source_wbk.Close
End Sub
'Below in the code in the userform
Private Sub ListBox1_Click()
Sheets(ListBox1.Value).Activate
Unload Me
End Sub
Private Sub UserForm_Initialize()
Dim sh As Worksheet
strfile = ("C:\Documents\" & sourcefilename)
Set wbk = Workbooks.Open(strfile, ReadOnly:=True)
For Each sh In wbk.Sheets
ListBox1.AddItem sh.Name
Next sh
End Sub
You need to change your two variables dest_wbk and dest_ws to something like
In case your destination Workbook is already open
'Change Workbook2.xls to whatever the file is (assuming it is open already)
Set dest_wbk = Workbooks("Workbook2.xls")
'Change SheetName to whatever the sheet name is inside dest_wbk
Set dest_ws = dest_wbk.Sheets("SheetName")
Otherwise, you need to open the workbook
'Change Workbook2.xls to whatever the file is
Set dest_wbk = Workbooks.Open("Workbook2.xls")
'Change SheetName to whatever the sheet name is inside dest_wbk
Set dest_ws = dest_wbk.Sheets("SheetName")
It is up to you, to get those values (Workbook name and Sheet name) from the UserForm, which I believe it shouldn't be a problem for you.

Run VBA macro in another workbook while using main workbook [duplicate]

I have a workbook which opens up another workbook (filename is based on a cell value) and then runs a macro called Single_sector within that file.
It opens the file perfectly fine but doesn't run the macro. Any ideas?
Sub run_all()
Dim Location
On Error Resume Next
'Location of file to open
Location = Worksheets("Main").Range("folder_location").Value
'Open F&V File
Application.Workbooks.Open Location & Range("fv_file").Value
'Run Macro
Run ("Single_sector")
End Sub
Place the following code in the macro calling the other workbook:
Location = Worksheets("Main").Range("folder_location").Value
Set wb = Workbooks.Open(Location & Range("fv_file").Value)
Application.Run "'" & wb.Name & "'!" & strSubToRun, Parameters
Set wb = Nothing
Parameters is an array of arguments that you want to pass, so the sub in the other workbook should look something like
Public Sub TheSub(ParamArray X())
Dim i As Long
Sheet1.Cells(1, 1).Value = "Parameters passed:"
For i = 0 To UBound(X(0))
Sheet1.Cells(i + 2, 1).Value = CStr(X(i))
Next
End Sub
Probably not very elegant but:
Dim Location As String
Location = "\\location\to\file.xlsm"
Workbooks.Open(Location).RunAutoMacros (xlAutoOpen)
Where you have an Auto_Open Sub in your other excel file to handle the macros to run on your other spreadsheet
Please make sure your code in another workbook is at Workbook_open event so you dont need to use Run ("Single_sector"). The procedure single_selector would trigger as soon as another workbook is open.
Updated answer
Sub run_all()
Dim Location
On Error Resume Next
Dim wkb As Workbook
'Location of file to open
Location = Worksheets("Main").Range("folder_location").Value
'Open F&V File
Set wkb = Workbooks.Open(Location & Range("fv_file").Value)
wkb.Sheets(1).Single_sector ' kindly put this proc in another workbook sheet1
End Sub

VBA to copy Module from one Excel Workbook to another Workbook

I am trying to copy a module from one excel workbook to another using VBA.
My Code:
'Copy Macros
Dim comp As Object
Set comp = ThisWorkbook.VBProject.VBComponents("Module2")
Set Target = Workbooks("Food Specials Rolling Depot Memo 46 - 01.xlsm").VBProject.VBComponents.Add(1)
For some reason, this copies the module, but does not copy the VBA code inside, why?
Please can someone show me where i am going wrong?
Thanks
Sub CopyModule below, receives 3 parameters:
1.Source Workbook (as Workbook).
2.Module Name to Copy (as String).
3.Target Workbook (as Workbook).
CopyModule Code
Public Sub CopyModule(SourceWB As Workbook, strModuleName As String, TargetWB As Workbook)
' Description: copies a module from one workbook to another
' example: CopyModule Workbooks(ThisWorkbook), "Module2",
' Workbooks("Food Specials Rolling Depot Memo 46 - 01.xlsm")
' Notes: If Module to be copied already exists, it is removed first,
' and afterwards copied
Dim strFolder As String
Dim strTempFile As String
Dim FName As String
If Trim(strModuleName) = vbNullString Then
Exit Sub
End If
If TargetWB Is Nothing Then
MsgBox "Error: Target Workbook " & TargetWB.Name & " doesn't exist (or closed)", vbCritical
Exit Sub
End If
strFolder = SourceWB.Path
If Len(strFolder) = 0 Then strFolder = CurDir
' create temp file and copy "Module2" into it
strFolder = strFolder & "\"
strTempFile = strFolder & "~tmpexport.bas"
On Error Resume Next
FName = Environ("Temp") & "\" & strModuleName & ".bas"
If Dir(FName, vbNormal + vbHidden + vbSystem) <> vbNullString Then
Err.Clear
Kill FName
If Err.Number <> 0 Then
MsgBox "Error copying module " & strModuleName & " from Workbook " & SourceWB.Name & " to Workbook " & TargetWB.Name, vbInformation
Exit Sub
End If
End If
' remove "Module2" if already exits in destination workbook
With TargetWB.VBProject.VBComponents
.Remove .Item(strModuleName)
End With
' copy "Module2" from temp file to destination workbook
SourceWB.VBProject.VBComponents(strModuleName).Export strTempFile
TargetWB.VBProject.VBComponents.Import strTempFile
Kill strTempFile
On Error GoTo 0
End Sub
Main Sub Code (for running this code with the Post's data):
Option Explicit
Public Sub Main()
Dim WB1 As Workbook
Dim WB2 As Workbook
Set WB1 = ThisWorkbook
Set WB2 = Workbooks("Food Specials Rolling Depot Memo 46 - 01.xlsm")
Call CopyModule(WB1, "Module2", WB2)
End Sub
Actually, you don't need to save anything to a temporary file at all. You can use the .AddFromString method of the destination module to add the string value of the source. Try the following code:
Sub CopyModule()
Dim SourceVBProject As VBIDE.VBProject, DestinationVBProject As VBIDE.VBProject
Set SourceVBProject = ThisWorkbook.VBProject
Dim NewWb As Workbook
Set NewWb = Workbooks.Add ' Or whatever workbook object you have for the destination
Set DestinationVBProject = NewWb.VBProject
'
Dim SourceModule As VBIDE.CodeModule, DestinationModule As VBIDE.CodeModule
Set SourceModule = SourceVBProject.VBComponents("Module1").CodeModule ' Change "Module1" to the relevsant source module
' Add a new module to the destination project
Set DestinationModule = DestinationVBProject.VBComponents.Add(vbext_ct_StdModule).CodeModule
'
With SourceModule
DestinationModule.AddFromString .Lines(1, .CountOfLines)
End With
End Sub
Should be self-explanatory! The .AddFomString method simply takes a string variable. So in order to get that, we use the .Lines property of the source module. The first argument (1) is the start line, and the second argument is the end line number. In this case, we want all the lines, so we use the .CountOfLines property.
Fantastic Code by Chris Melville, Thanks a ton, just a few small addition which i did & added few comments.
Just make sure, following things are done before running this macro.
VB Editor > Tools > References > (Check) Microsoft Visual Basic for Applications Extensibility 5.3
File -> Options -> Trust Center -> Trust Center Setttings -> Macro Settings -> Trust Access to the VBA Project object model.
Once you do above thing, copy & paste below code in Source File
Sub CopyMacrosToExistingWorkbook()
'Copy this VBA Code in SourceMacroModule, & run this macro in Destination workbook by pressing Alt+F8, the whole module gets copied to destination File.
Dim SourceVBProject As VBIDE.VBProject, DestinationVBProject As VBIDE.VBProject
Set SourceVBProject = ThisWorkbook.VBProject
Dim NewWb As Workbook
Set NewWb = ActiveWorkbook ' Or whatever workbook object you have for the destination
Set DestinationVBProject = NewWb.VBProject
'
Dim SourceModule As VBIDE.CodeModule, DestinationModule As VBIDE.CodeModule
Set SourceModule = SourceVBProject.VBComponents("Module1").CodeModule ' Change "Module1" to the relevsant source module
' Add a new module to the destination project
Set DestinationModule = DestinationVBProject.VBComponents.Add(vbext_ct_StdModule).CodeModule
'
With SourceModule
DestinationModule.AddFromString .Lines(1, .CountOfLines)
End With
End Sub
Now run the "CopyMacrosToExistingWorkbook" macro in destination file, you will see the source file macro copied to destination file.
I had a lot of trouble getting the previous answers to work, so I thought I'd post my solution. This function is used to programmatically copy modules from a source workbook to a newly created workbook that was also created programmatically with a call to worksheet.copy. What doesn't happen when a worksheet is copied to a new workbook is the transfer of the macros that the worksheet depends upon. This procedure iterates through all modules in the source workbook and copies them into the new one. What's more is that it actually worked for me in Excel 2016.
Sub CopyModules(wbSource As Workbook, wbTarget As Workbook)
Dim vbcompSource As VBComponent, vbcompTarget As VBComponent
Dim sText As String, nType As Long
For Each vbcompSource In wbSource.VBProject.VBComponents
nType = vbcompSource.Type
If nType < 100 Then '100=vbext_ct_Document -- the only module type we would not want to copy
Set vbcompTarget = wbTarget.VBProject.VBComponents.Add(nType)
sText = vbcompSource.CodeModule.Lines(1, vbcompSource.CodeModule.CountOfLines)
vbcompTarget.CodeModule.AddFromString (sText)
vbcompTarget.Name = vbcompSource.Name
End If
Next vbcompSource
End Sub
The function should hopefully be as simple as possible and fairly self-explanatory.
You can try
Open both workbooks
Open VBA Dev window
Dropdown Modules and drag and drop a copy from one module are to another
This is to make sure Module Names are not duplicated.
Also if you have modules that contain same named function / Subs then there will be a clash.
I do this and then run debug. Seems to work fine.
P.S. I copy many in to my PERSONAL.xlsb

Rename Workbook with name of first worksheet VBA

I would like to rename each workbook in a folder as the name of the first worksheet in the workbook. For example, if the Workbook is called "71107" and the worksheet in that workbook is called "foobar", I would like the workbook to be renamed "foobar".
My current progress is as follows:
Sub RunMe()
Dim objFSO As New FileSystemObject
Dim objWkbk As Workbook
Dim objFile As File
Dim folderpath As String
Application.ScreenUpdating = False
folderpath = "D:\test\"
For Each objFile In objFSO.GetFolder(folderpath).Files
oldpath = objFile.path
Set objWkbk = Workbooks.Open(oldpath)
newpath = path & "NEWNAME\" & ActiveSheet.Name & ".xls"
objWkbk.SaveAs Filename:=newpath
objWkbk.Close
Next objFile
End Sub
This code runs extremely slowly (in the order of 10 seconds per file). My files are not large, only around 40kb each. Is there a faster way to perform this operation? I also don't need to save a new copy of each file, I'm quite happy to just rename the file I just don't know of a way to do that.
There are two things, which takes so long one is Open and SaveAs.
The Open can be avoided with ADO as mentioned and more details are here
Then you can also not use SaveAs because it is not opened but you can just rename the file using something like:
Name GivenLocation & OldFileName As GivenLocation & NewFileName

Trying to open a Workbook and a run a macro in that file

I have a workbook which opens up another workbook (filename is based on a cell value) and then runs a macro called Single_sector within that file.
It opens the file perfectly fine but doesn't run the macro. Any ideas?
Sub run_all()
Dim Location
On Error Resume Next
'Location of file to open
Location = Worksheets("Main").Range("folder_location").Value
'Open F&V File
Application.Workbooks.Open Location & Range("fv_file").Value
'Run Macro
Run ("Single_sector")
End Sub
Place the following code in the macro calling the other workbook:
Location = Worksheets("Main").Range("folder_location").Value
Set wb = Workbooks.Open(Location & Range("fv_file").Value)
Application.Run "'" & wb.Name & "'!" & strSubToRun, Parameters
Set wb = Nothing
Parameters is an array of arguments that you want to pass, so the sub in the other workbook should look something like
Public Sub TheSub(ParamArray X())
Dim i As Long
Sheet1.Cells(1, 1).Value = "Parameters passed:"
For i = 0 To UBound(X(0))
Sheet1.Cells(i + 2, 1).Value = CStr(X(i))
Next
End Sub
Probably not very elegant but:
Dim Location As String
Location = "\\location\to\file.xlsm"
Workbooks.Open(Location).RunAutoMacros (xlAutoOpen)
Where you have an Auto_Open Sub in your other excel file to handle the macros to run on your other spreadsheet
Please make sure your code in another workbook is at Workbook_open event so you dont need to use Run ("Single_sector"). The procedure single_selector would trigger as soon as another workbook is open.
Updated answer
Sub run_all()
Dim Location
On Error Resume Next
Dim wkb As Workbook
'Location of file to open
Location = Worksheets("Main").Range("folder_location").Value
'Open F&V File
Set wkb = Workbooks.Open(Location & Range("fv_file").Value)
wkb.Sheets(1).Single_sector ' kindly put this proc in another workbook sheet1
End Sub