I have a load of data which I need to process. I process it by pasting the raw data into a pre-made excel spreadsheet, trimming a few rows of zeros at the bottom of the processing (not pasted in) columns, and then running a macro to remove cells with 0 in them in column P.
Each spreadsheet takes 6 sets of raw data, each in a separate worksheet. The zero-removing macro takes a while so I would like to do the pasting as a separate job if I can.
I feel like this should be pretty simple but unfortunately I only have a very basic knowledge of code. My idea so far has been to try and use AutoHotKey to record a sequence to do it, but unfortunately it is clunky and hasn't worked so far because alt-tabbing is unreliable or some other issue.
I would like to make a code which switches between windows, copying the data from one excel (tab delimited .txt) file into the main .xlsm document.
I would manually save it and then open the next 6 datasets and a blank processing workbook.
Thanks for your time x
Edit: The datasets are always called a,a1,a2,b,b1,b2. They are always located in the same folder as the data processing spreadsheet. The data processing spreadsheet is always called [processor.xlsm]
Edit2: This is where I am:
Sub ImportData1()
'Prevent windows asking about saving clipboard data
Application.DisplayAlerts = False
'select dataset a
Worksheets("SeqA Run1").Activate
Workbooks.Open Filename:=ThisWorkbook.Path & "\a.txt"
ActiveSheet.Range("A4:I1000").Copy
Windows("Surge Test Data Analysis Importer.xlsm").Activate
Range("A7").Select
ActiveSheet.Paste
''Close dataset
Windows("a.txt").Activate
ActiveWorkbook.Close
'Select dataset a1
Worksheets("SeqA Run2").Activate
Workbooks.Open Filename:=ThisWorkbook.Path & "\a1.txt"
ActiveSheet.Range("A4:I1000").Copy
Windows("Surge Test Data Analysis Importer.xlsm").Activate
Range("A7").Select
ActiveSheet.Paste
''Close dataset
Windows("a1.txt").Activate
ActiveWorkbook.Close
'(repeat several times)
'Re-enable windows prompts about clipboards etc
Application.DisplayAlerts = True
End Sub
You do not need to switch between windows. You have to get references to the worksheets, and use the references. The first thing to do is record a macro, and then do whatever you would do, manually. Stop recording, and then start modifying the resulting macro.
Then, in your macro,
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set wb1 = Workbooks("<The name of your target Workbook>")
Set wb2 = Workbooks("<The name of your source Workbook>")
Set ws1 = wb1.Worksheets("<The name of your target> Worksheet")
Set ws2 = wb2.Worksheets("<The name of your source> Worksheet")
ws2.UsedRange.Copy
ws1.Paste
You may need to paste at a specific location in your Target.
Repeating requires looping (e.g., For ... Next). If you provide more info on your case, it would be helpful.
Remember that assigning to a variable of type Worksheet should be preceded by Set.
Related
I use this piece of code:
Application.Workbooks(V_WBNameOutPut).Activate
to activate a particular excel file, I notice that this method goes in error if the "File name extension" (in the View tab of the Folder Menu) is flagged.
In order to be independent of this, what modification should I do/include to the code or what alternative method should I use?
This answer is based on the comment
I interchange many times during the macro run between 2 workbooks, input and output
excel files, and I need to activate the V_WBNameOutPut, to paste and elaborate, and > this is done multiple times during the run. From the input file, I create the > V_WBNameOutPut file.
As #brax said - capture the workbook when it's opened and you don't have to worry about the extension after that.
Sub Test()
'Open the first workbook and store reference to it.
Dim wrkBk1 As Workbook
Set wrkBk1 = Workbooks.Open("H:\Darren Bartrup-Cook\Test 1.xlsx")
'Open the second workbook and store reference to it.
Dim wrkBk2 As Workbook
Set wrkBk2 = Workbooks.Open("H:\Darren Bartrup-Cook\Test 2.xlsx")
'Copy/paste from wrkbk1 to wrkbk2.
wrkBk1.Worksheets("Sheet1").Range("A1").Copy Destination:=wrkBk2.Worksheets("Sheet1").Range("A4")
'Create a new sheet in wrkbk2.
Dim NewWrkSht As Worksheet
Set NewWrkSht = wrkBk2.Worksheets.Add
NewWrkSht.Name = "My New Sheet"
'Paste copy/paste values from wrkbk1 to wrkbk2.
wrkBk1.Worksheets("Sheet1").Range("A2").Copy
NewWrkSht.Range("A5").PasteSpecial Paste:=xlPasteValues
'Make A3 in wrkbk2 equal the value in wrkbk1 A3.
wrkBk2.Worksheets("Sheet1").Range("A3") = wrkBk1.Worksheets("Sheet1").Range("A3")
'Close the two workbooks.
wrkBk2.Close SaveChanges:=True
wrkBk1.Close SaveChanges:=False
End Sub
I am a completely new to VBA
The goal of my code below is to open another excel workbook on a networked drive that's name changes with the month, copy and paste that data into thisworkbook, and close the file I just opened once its done with its task.
When I F8 through the VBA Editor this code actually works, as it in opens the excel file / copy pastes data, however I'm getting a yellow highlight around the filepath string that I made a variable when I try to actually run the macro (and it does not work).
The filepath is a concatenation of the text&cellreference&text within the Excel workbook, I'm wondering if that is causing the problem. The text is the filepath, the cell reference is the changing month. The month in the filepath is spelled out, aka C:...\location\November 2020 report.xlsx
Sub CopyDay1Report()
Dim Day1Report As Variant
Day1Report = Curtailment.Range("Q4")
'GVS1
Excel.Workbooks.Open (Day1Report)
Sheets("GVS1").Range("A1:M16").Copy
ThisWorkbook.Activate
Range("B27:N42").PasteSpecial xlPasteValuesAndNumberFormats
'GVS2
Excel.Workbooks.Open (Day1Report)
Sheets("GVS2").Range("A1:M16").Copy
ThisWorkbook.Activate
Range("B47:N62").PasteSpecial xlPasteValuesAndNumberFormats
'GVS3
Excel.Workbooks.Open (Day1Report)
Sheets("GVS3").Range("A1:M16").Copy
ThisWorkbook.Activate
Range("B66:N81").PasteSpecial xlPasteValuesAndNumberFormats
'GVS4
Excel.Workbooks.Open (Day1Report)
Sheets("GVS4").Range("A1:M16").Copy
ThisWorkbook.Activate
Range("B84:N99").PasteSpecial xlPasteValuesAndNumberFormats
Workbooks("Day1Report").Close SaveChanges:=False
I have a macro in Excel 2019 which runs in less than one second directly through VBE (by pressing F5), or when I configure a button to the macro in the Ribbon (through options>customize ribbon).
When I create a button (FormControlButton) inside the sheet area, and associate the macro, it takes at least seven seconds.
The macro runs without any error message. Other macros are slower as well, but this one is the most noticeable.
My macro builds a jagged array with data (~4000 records) that is in another sheet, then sorts the array by bubble/quicksorting (tested both to check if the problem could be here, and it wasn't), then filters it and returns data in a new sheet.
The macros where designed in Excel 2010, and I noticed the problem right after our company updated Microsoft Office from 2010 to 2019. (Windows was updated the same day from 2007 to 10, but I think the problem is in Excel, as I tested it again in some PCs that still had Office 2010 and the macros worked as fast as if run through VBE). Creating and editing macros is not prohibited by administrators.
Adding more information as requested:
I didn't add code because it's not a problem of a specific macro, but I noticed the ones that slowed most are the ones that interact with arrays. Besides that, as it didn't happen when I used buttons inside a sheet in Office 2010, maybe it's a bug in Office 2019.
One thing in common in all my macros is that I follow Microsoft's recommendations to speed up macros, and I use this chunk of code:
Sub SubName()
Call DeactivateSystemFunctions
'Rest of the code
Call ReactivateSystemFunctions
End Sub
Where
Sub DeactivateSystemFunctions()
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.Calculation = xlCalculationManual
Application.ActiveSheet.DisplayPageBreaks = False
Application.EnableEvents = False
End Sub
Sub ReactivateSystemFunctions()
Application.ScreenUpdating = True
Application.DisplayStatusBar = True
Application.Calculation = xlCalculationAutomatic
Application.ActiveSheet.DisplayPageBreaks = True
Application.EnableEvents = True
End Sub
I don't use .activate or .select in any of my macros, and while formatting I always try to put the max inside a With/End With.
My macro was working fine through VBE but taking too many time when activated through a FormControlButton inside my sheet. As #RonRosenfeld suggested, I had to set a timer to each specific part of my code to find where the problem was. I put the timer at the beggining of my code and I had to move the command to stop the timer to each part of it until I found where it was getting slow.
My macro creates a jagged array and then sorts it through Quicksorting, and as the quicksort I made takes more than one criteria to sort, I thought the problem might be occurring there, as it is a recursive method.
But actually the problem was happening when I was printing the results of the sorted jagged array in another worksheet I create using the same macro.
I print data this way:
NewSheet.Cells(NewSheetRow, Column1) = SortedArray(RecordNumber)(DesiredInfo1 - 1)
NewSheet.Cells(NewSheetRow, Column2) = SortedArray(RecordNumber)(DesiredInfo7 - 1)
NewSheet.Cells(NewSheetRow, Column3) = SortedArray(RecordNumber)(DesiredInfo14 - 1)
'As my jagged array is built with data from a Source Worksheet:
'RecordNumber is the (Row - 1) in the source worksheet
'DesiredInfoX is the Column in the source worksheet
The problem happened only when printing specific Columns. The source sheet has different columns, each with a different data format. The only data format that slowed things down was strings.
I went to the source worksheet and noticed some problems:
As the file went from excel 2000 to 2010 to 2019 and data was not migrated but simply saved from .xls to .xlsm, when I went to the end of the source sheet, I noticed it had only 65536 rows (not 1048576 as expected), but had 16384 columns (last=XFD).
It was only happening with the source sheet, which is the one we have more data in. Other sheets in the same workbook had the expected 1048576 rows and 16384 columns.
After we started using excel 2019, some of the data that was supposed to be String(Text), was formatted as GENERAL/NUMBER. I can't affirm it was not human error, but our source sheet is filled by macro, not by human, and the macro forces formatting of each data.
What I did to solve the problem:
I migrated all data from all sheets, to a new workbook using VBA, not copy/paste. After passing the values to the new source sheet, I forced the formatting of each column. All macros had to be migrated as well.
After that, the FormControlButton inside the sheet is working as fast as activating the macro directly through VBE by pressing F5.
If anybody needs:
'###Timer code
'Got it from https://www.thespreadsheetguru.com/the-code-vault/2015/1/28/vba-calculate-macro-run-time
'Put this part in the beggining of your code
Dim StartTime As Double
Dim SecondsElapsed As Double
'Remember time when macro starts
StartTime = Timer
'Put this part where you want the timer to stop
'Determine how many seconds code took to run
SecondsElapsed = Round(Timer - StartTime, 2)
'Notify user in seconds
MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation
'###Migration macro:
Sub Migrate()
Call DeactivateSystemFunctions
'Source File
Dim XLApp As Object
Dim WbSource As Object
Dim WsSource As Object
Set XLApp = CreateObject("Excel.Application")
XLApp.Visible = False
Set WbSource = XLApp.Workbooks.Open("C:\FolderFoo\FolderBar\Desktop\SourceFileName.Extension")
Set WsSource = WbSource.Worksheets("SourceWorksheetName")
'Destination File. May be set as source file or if using this workbook by simply:
Dim WsDest As Worksheet
Set WsDest = ThisWorkbook.Worksheets("DestinationSheetName")
Dim BDR As Long
Dim BDC As Long
Dim UltR As Long
Dim UltC As Long
UltR = WsSource.Cells(Rows.Count, 1).End(xlUp).Row
UltC = WsSource.Cells(1, Columns.Count).End(xlToLeft).Column
For BDR = 1 To UltR
For BDC = 1 To UltC
If WsSource.Cells(BDR, BDC) <> vbEmpty Then
WsDest.Cells(BDR, BDC) = WsSource.Cells(BDR, BDC)
End If
Next BDC
Next BDR
'Format your columns as needed
With WsDest
.Columns(Column1Number).NumberFormat = "0"
.Columns(Column2Number).NumberFormat = "dd/mm/yyyy"
.Columns(Column3Number).NumberFormat = "#"
.Columns(Column4Number).NumberFormat = "#"
.Columns(Column5Number).NumberFormat = "0.000"
End With
WbSource.Close SaveChanges:=False
Call ReactivateSystemFunctions
End Sub
TLDR: I had the same problem and I think it's the fault of the mouse pointer.
My solution:
Dim Cursor As XlMousePointer
Cursor = Application.Cursor
Application.Cursor = xlWait
-- YOUR CODE HERE --
Application.Cursor = Cursor
Long Version:
I noticed a similar problem in one of my macros and it seems to occur when lots of cells are manipulated individually (i.e. looping through hundreds or thousands of cells and changing their values).
You might notice the mousepointer changing eratically when you start it from the FormButton or ActiveX Button, but when you start the macro from VBE, it does not do that.
In my case, the macro even started to run faster if I took the focus off the excel window - something as simple as moving the mouse over the windows start-menu button or over an application in the windows taskbar improved the performance of the macro.
I did not research this further, but I concluded that the erratic changes to the mousepointer were in fact the killer to the performance, so I did the following:
Before changing the cells, I set the mousepointer to something other than "Default". When you do that it stays there and does not change while you manipulate the cells. After that I set the mousepointer to whatever status it had before my macro.
I did not have the same problem since.
I have what it seems a small issue but cannot figure out how to solve.
So, every week I have to make a bunch of pivot tables to summarize raw data that I am getting. I figured, it would be much easier if I create all the tables into a Layout file and then just copy them to the new file and then change the source. And I wrote the following code:
Sub something()
Workbooks.Open Filename:="C:\\\\Layout.xlsx"
With Workbooks("Layout.xlsx")
.Sheets("Pivot").Copy Before:=ActiveWorkbook.Sheets("Main List")
.Close savechanges:=False
End With
End Sub
This code works just fine. The issue comes when I try to paste the code into my personal workbook and then run through VBA directly, rather than copying and pasting it every time.
What I could do is, to change the code from 'Activeworkbook' to the name of my new workbook but its name change every week, because it is based on a date.
I already tried to declare the name of the new workbook as a string and call it through that but that didn't work either.
Any ideas?
I would use workbook objects to keep the two files clear:
Sub something()
Dim wb_from As Workbook, wb_to As Workbook
Set wb_to = ActiveWorkbook
Workbooks.Open Filename:="C:\\\\Layout.xlsx"
Set wb_from = Workbooks("Layout.xlsx")
wb_from.Sheets("Pivot").Copy Before:=wb_to.Sheets("Main List")
wb_from.Close SaveChanges:=False
end sub
We have 2 different files with basic vlookup infos:
Source file is: JP2-CSV CRAWLER
Destination file is: JP2-CATEGORIES
We are trying to copy one full column from the Source file to the first column of the destination file automatically ( It should work when opening it or using it)
That's our code:
Sub Copysubcat()
Dim wbSource As Workbook
Dim wbDestination As Workbook
Set wbSource = Workbooks.Open( _
Filename:="C:\Users\user\Desktop\crawler file\JP2-CSV CRAWLER.xlsx")
Set wbDestination = Workbooks("C:\Users\user\Desktop\crawler file\JP2-CATEGORIES.xlsx")
wbSource.Sheets("CSV Crawler").Range("P2:P10000").Copy
wbDestination.Sheets("Cats & Subcats").Range("A2:A10000").PasteSpecial (xlPasteValues)
Application.CutCopyMode = False
ActiveWorkbook.Save
End Sub
We are having an error "Subscript out of range"
Anybody could help on that?
Workbooks isn't a method, so it cannot take any parameters. This is class, which represents workbooks, which contains methods to handle them. One of them is Open which you will need in this case. So you'll need to switch this:
Set wbDestination = Workbooks("C:\Users\user\Desktop\crawler file\JP2-CATEGORIES.xlsx")
to this:
Set wbDestination = Workbooks.Open("C:\Users\user\Desktop\crawler file\JP2-CATEGORIES.xlsx")
Also, there is an event such as opening the workbook, you can place your corrected code there, so the macro would run every time this event is raised (i.e. on every opening). If you are using standard VBA development environment in Excel, click on This_workbook on right side (in tree view), you will have to dropdown lists at the top, in the one on the left choose Workbook, in the other one select Open (this is list of events, that is raised by Workbook). Then, inside generated method place youre code :)