Excel VBA: Loop through sheets / transfer data / create new workbook for each - vba

could you please help me out adjusting my macro?
What I have
Selecting different workbooks(wb1,wb2...) via a file explorer dialog
window and listing them in a listbox
Transfering certain data from the selected workbooks to a workbook
template(wb_template) and saving it as a new workbook.
The new workbook contains the data from wb_1, but the structure of
wb_template The User Form Looks like this:
What I need
I need to adjust the way the relevant data from the workbooks is selected("Transfer-data" button). I would need a loop which is going through every sheet of wb_1 and is covering the following:
Look for certain terms in wb_1 and move/rename them to wb_template in specific sheet/column/cell.
Example:
Look for certain terms in wb_1 and just take the value, which is stored in the cell on the right side of it, and move to wb_template in specific sheet/column/cell.
Example:
The steps above should be applied to every sheet of wb_1 and for every sheet should be a new workbook created.
So, at the end of the process I should have a new workbook for every sheet in wb_1.
For example: if wb_1 has 5 sheets, there should be 5 new workbooks created (wb1_1, wb1_2, wb1_3,...).
​
Here is a simple overview visual showing what I exactly want to achieve with this macro:
My actual code
Transfer Data Button
Sub Transferfile(wbTempPath As String, wbTargetPath As String)
Dim wb1 As Workbook
Dim wb_template As Workbook
Set wb1 = Workbooks.Open(wbTargetPath)
Set wb_template = Workbooks.Open(wbTempPath)
'/* Definition of the value range */
wb_template.Sheets("Sheet1").Range("A2").Value = wb1.Sheets("Sheet1").Range("A2").Value
wb_template.Sheets("Sheet1").Range("A3").Value = wb1.Sheets("Sheet1").Range("A3").Value
wb_template.Sheets("Sheet1").Range("B2").Value = wb1.Sheets("Sheet1").Range("B2").Value
wb_template.Sheets("Sheet1").Range("B3").Value = wb1.Sheets("Sheet1").Range("B3").Value
wb1Name = Left(wb1.Name, InStr(wb1.Name, ".") - 1)
wb_template.SaveAs wb1.Path & "\" & wb1Name & "_New.xlsx"
wb1.Close False
wb_template.Close False
End Sub
Browse File Button - I guess not so relevant for this topic
Private Sub CommandButton1_Click()
Dim fNames As Variant
With Me
fNames = Application.GetOpenFilename("Excel File(s) (*.xls*),*.xls*", , , , True)
If IsArray(fNames) Then .ListBox1.List = fNames
End With
End Sub
​
Private Sub CommandButton2_Click()
Dim i As Integer
'/* full path to the template file */
Const mytemplate As String = "C:\Users\PlutoX\Desktop\Excel-Folder\wb_template.xlsx"
With Me
With .ListBox1
'/* iterate listbox items */
For i = 0 To .ListCount - 1
'/* transfer the files using the generic procedure */
Transferfile mytemplate, .List(i, 0)
Next
End With
End With
End Sub​
Thanks for the help!
Summary:
I need to search for for specific keywords in a sheet of wb1.
I dont know the positions of those keywords
In case a keyword is found - condition1 or condition2 will be applied, depending on the keyword:
Condition 1: if keyword in wb1 = "House_1" then copy/paste keyword in wb2 (specific position -> Sheet2, A3) and rename it to
"House Blue".Result would be: "House Blue" in A3 of Sheet2 in wb2.
Condition 2: if keyword in wb1 = "Number" then copy the value of the adjoining cell to the right of it and paste in wb2 (specific
position -> Sheet3, C5).Result would be: "4" in C5 of Sheet3 in wb2.
So what I want to do is to determine the relevant keywords - and which condition the respective keyword is triggering.
Update:
I dont know the specific sheet, so every sheet in the wb should be checked
Actually, my goal is to have a set of keywords, which have condition 1 or condition 2 assigned, as well as a specific paste-location in wb_template. So, every sheet should be checked according to the set of keywords. A keyword can only have one of the conditions assigned.

If the challenge you are facing is to find a specific word which could be lying anywhere in the workbook you can make use of Excel's inbuilt function "Find" with slight modification.
I will post a sample snippet which does the same. Please modify it accordingly.
Code Snippet: [ Tried & tested ]
Sub FindMyWord()
Dim sht As Worksheet
For Each sht In ThisWorkbook.Sheets 'Change workbook object accordingly
Dim CellWhereWordIs As Range
Set CellWhereWordIs = sht.Cells.Find("Charlie", LookIn:=xlValues, Lookat:=xlWhole, MatchCase:=False)
'Charlie is the word I wanna find. Change parmeters accordingly
If Not CellWhereWordIs Is Nothing Then
'Do something here
MsgBox "Word found in: " & sht.Name & "/" & CellWhereWordIs.Address
Else
MsgBox "Word not found in " & sht.Name, vbExclamation
End If
Next
End Sub

I think you just need to wrap your code into a loop going through all the worksheets.
I also recommend to use a bit more descriptive variable names: wb1 is not very descriptive but if you change it to wbSource it is very clear that this is the workbook where the data comes from.
Finally I recommend to use Application.PathSeparator instead of "\" to make it independent form your operating system (eg. MacOS uses "/" instead of "\").
Option Explicit
Public Sub TransferFile(TemplateFile As String, SourceFile As String)
Dim wbSource As Workbook
Set wbSource = Workbooks.Open(SourceFile) 'open source
Dim wbTemplate As Workbook
Dim NewWbName As String
Dim wsSource As Worksheet
For Each wsSource In wbSource.Worksheets 'loop through all worksheets in source workbook
Set wbTemplate = Workbooks.Open(TemplateFile) 'open new template
'/* Definition of the value range */
With wbTemplate.Worksheets("Sheet1")
.Range("A2").Value = wsSource.Range("A2").Value
.Range("A3").Value = wsSource.Range("A3").Value
.Range("B2").Value = wsSource.Range("B2").Value
.Range("B3").Value = wsSource.Range("B3").Value
End With
NewWbName = Left(wbSource.Name, InStr(wbSource.Name, ".") - 1)
wbTemplate.SaveAs wbSource.Path & Application.PathSeparator & NewWbName & "_New.xlsx"
wbTemplate.Close False 'close template
Next wsSource
wbSource.Close False 'close source
End Sub

Related

VBA import data: exclude sheet if doesn't exist

I have built this code which import data from a workbook and paste it to another one. The original workbook is composed by hundred of sheets (one sheet for each country, identified by the ISO 2 digit code: AE, AL, AM, AR etc...). The macro is opening each one of these sheets, copying the same cell, and printing all these cells in a new workbook.
The problem is that if, for example, the sheet F(AM) doesn't exists, the macro stops. I would like to make sure that if a sheet doesn't exist, the macro continues with all the other sheets (namely F(AR), F(AT), F(AU)) till the end.
Someone has any suggestion?
Many thanks in advance!
Sub ImportData()
Dim Wb1 As Workbook
Dim MainBook As Workbook
Dim Path As String
Dim SheetName As String
'Specify input data
Path = Worksheets("Input").Range("C6").Value
'Decide in which target sheet print the results
SheetName = "Data"
'From which sheets you need to take the data?
OriginSheet145 = "F(AE)"
OriginSheet146 = "F(AL)"
OriginSheet147 = "F(AM)"
OriginSheet148 = "F(AR)"
OriginSheet149 = "F(AT)"
OriginSheet150 = "F(AU)"
'Set the origin workbook
Set Wb1 = Workbooks.Open(Path & "_20171231.xlsx")
'Set the target workbook
Set MainBook = ThisWorkbook
'Vlookup to identify the correct data point
Wb1.Sheets(OriginSheet145).Range("N25").FormulaR1C1 = "=VLOOKUP(""010"",C[-10]:C[-7],2,FALSE)"
Wb1.Sheets(OriginSheet146).Range("N26").FormulaR1C1 = "=VLOOKUP(""010"",C[-10]:C[-7],2,FALSE)"
Wb1.Sheets(OriginSheet147).Range("N27").FormulaR1C1 = "=VLOOKUP(""010"",C[-10]:C[-7],2,FALSE)"
Wb1.Sheets(OriginSheet148).Range("N28").FormulaR1C1 = "=VLOOKUP(""010"",C[-10]:C[-7],2,FALSE)"
Wb1.Sheets(OriginSheet149).Range("N29").FormulaR1C1 = "=VLOOKUP(""010"",C[-10]:C[-7],2,FALSE)"
Wb1.Sheets(OriginSheet150).Range("N30").FormulaR1C1 = "=VLOOKUP(""010"",C[-10]:C[-7],2,FALSE)"
'Copy the data point and paste in the target sheet
Wb1.Sheets(OriginSheet145).Range("N25").Copy
MainBook.Sheets(SheetName).Range("AW5").PasteSpecial xlPasteValues
Wb1.Sheets(OriginSheet146).Range("N26").Copy
MainBook.Sheets(SheetName).Range("AW6").PasteSpecial xlPasteValues
Wb1.Sheets(OriginSheet147).Range("N27").Copy
MainBook.Sheets(SheetName).Range("AW7").PasteSpecial xlPasteValues
Wb1.Sheets(OriginSheet148).Range("N28").Copy
MainBook.Sheets(SheetName).Range("AW8").PasteSpecial xlPasteValues
Wb1.Sheets(OriginSheet149).Range("N29").Copy
MainBook.Sheets(SheetName).Range("AW9").PasteSpecial xlPasteValues
Wb1.Sheets(OriginSheet150).Range("N30").Copy
MainBook.Save
Wb1.Close savechanges:=False
MsgBox "Data: imported!"
End Sub
This function returns TRUE or FALSE, indicating whether a worksheet named in string wsName exists in workbook object
Function wsExists(wb As Workbook, wsName As String) As Boolean
Dim ws: For Each ws In wb.Sheets
wsExists = (wsName = ws.Name): If wsExists Then Exit For
Next ws
End Function
Us an IF statement to skip the applicable code if the worksheet does not exist.
Edit:
I can tell that you put a lot of work into your code, which is awesome, so don't take it the wrong way when I say it gave me anxiety so I had to simplify it. ...there are a lot of unneeded steps.
I do believe the "right way" is "whatever way works", so kudo's on getting this far. There's a steep learning curve in programming, so I figured I'd offer an alternate code block to replace yours. (The Option Explicit goes at the very top of the module, and will "force" you to properly declare/handle variables, objects, etc.)
Without seeing your data I can't guarantee this will work - in fact it very likely a cell reference wrong somewhere that you'll have to try to figure out - if you choose to use this at all.
Option Explicit
Sub ImportData()
Const SheetName = "Data" 'destination sheet name
Const sourceFile = "_20171231.xlsx" 'source filename for some reason
Dim wbSrc As Workbook, wbDest As Workbook, sht As Variant
Dim stPath As String, arrSourceSht() As Variant, inRow As Long
Set wbDest = ThisWorkbook 'dest wb object
stPath = Worksheets("Input").Range("C6").Value 'source wb stPath
'create array of source sheet names "146-150":
arrSourceSht = Array("F(AE)", "F(AL)", "F(AM)", "F(AR)", "F(AT)", "F(AU)")
Set wbSrc = Workbooks.Open(stPath & sourceFile) 'open source wb
With wbSrc
'VLookup to identify the correct data point
inRow = 5 'current input row
For Each sht In arrSourceSht
If wsExists(wbSrc, CStr(sht)) Then
wbDest.Sheets(sht).Range("AW" & inRow) = Application._
WorksheetFunction.VLookup("010", Range(.Sheets(sht).Range("N" & _
20 + inRow).Offset(-10), .Sheets(sht).Range("N" & 20 + inRow).Offset(-7)), 2, False)
End If
inRow = inRow + 1 'new input row
Next sht
wbDest.Save 'save dest
.Close savechanges:=False 'don't save source
End With
MsgBox "Data: imported!"
End Sub
Function wsExists(wb As Workbook, wsName As String) As Boolean
Dim ws: For Each ws In wb.Sheets
wsExists = (wsName = ws.Name): If wsExists Then Exit For
Next ws
End Function
Let me know if you have any questions, I can walk you through how it works if you like. (I'm on here at least once a day.)

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.

Range.Value not working for assigning cell contents to variable in VBA

I am writing my first script with VBA and I am having a hard time assigning the value entered into a cell to a String variable, I used Message Boxes to test where the issue is and it showed me I'm in the right workbook and the right sheet but then shows a blank for the value in "A1" even though I have a text value there and made sure I saved the workbook, what I have is below:
Sub copyworksheet()
Dim sourceWorkbook As String
Dim destinationWorkbook As String
Dim folderName As String
destinationWorkbook = ActiveWorkbook.Name
Sheets(1).Activate
MsgBox Range("A1").Value ' Shows blank when debugging
folderName = Range("A1").Value
MsgBox "Here is " & folderName ' Shows "Here is " when debugging
End Sub
** As an additional note, the A1 cell contains 02Nov, and I have tried changing the format of this cell and it hasn't fixed the issue, currently the cell format is Text
I think this should do the trick:
Sub copyworksheet()
Dim sourceWorkbook As String
Dim destinationWorkbook As String
Dim folderName As String
destinationWorkbook = ActiveWorkbook.Name
MsgBox Sheets(1).Range("A1").Value 'reference the Sheet absolutely when using Range
folderName = Sheets(1).Range("A1").Value
MsgBox "Here is " & folderName
End Sub
Alternate way is using Cells.
MsgBox Cells(1, 1).Value
folderName = Cells(1, 1).Value
Sheets(1)
refers to the first tab in the active workbook. That tab can be a worksheet, code sheet or chart sheet.
It is better to use WorkSheets() to reference worksheets. To ensure that you always get the correct sheet, regardless of order, use the name:
WorkSheets("Sheet1")
The best method would be to use the CodeName. This is the name of the sheet that the user cannot change. It is found in the sheet list in VBA:
The part before the () is the Codename. So Worksheets("Sheet1") Code Name is Sheet1. Using the code name we reference the sheet simply by typing it:
Sheet1
This cannot be easily changed by the user, as the name of the sheet can. This will always refer to the proper sheet regardless of tab position and name of the sheet.
Next:
Do not use .Activate or .Select They just slow down the code. Just append the ranges with the correct sheet references:
Worksheets("Sheet1").Range("A1")
Or better with the CodeName:
Sheet1.Range("A1")

Write from a worksheet to another using a macro added programmatically

I actually create worksheets programmatically and add button with a macro associated to these worksheets programmatically. What I want to do is that when I click on the button the content of the worksheet containing the button is copied to another worksheet.
There are actually two things that confuse me : Firstly I don't understand if the macro I associate to the button is located (I mean its code is located) in the file creating the worksheet or in the created worksheet itself.
Here is the code I create to add a button with an associated macro :
With newWorkBook.Worksheets(1).Buttons
.Add 350, 75, 173.25, 41.25
.OnAction = "'" & ThisWorkbook.FullName & "'!export_Click"
.Caption = "Exporter la fiche"
End With
newWorkBook.Worksheets("Feuil1").Name = "Valeurs"
The checkPVC_Click Sub is in a module located in the Excel file used to generate the worksheets.
Secondly, within the macro that is supposed to copy the content of a worksheet to another, I don't know how to refer differently to the two worksheets (source and target) in the code.
In the code below :
Dim newWorkBook As Workbook
Dim createdSheetColumnsTab(100) As String
Dim col As Integer
col = Cells(1, 8).Value
Set newWorkBook1 = Workbooks.Add
newWorkBook1.Worksheets("Feuil1").Cells(1, 1).Value = "Stat"
newWorkBook1.Worksheets("Feuil1").Cells(2, 1) = ActiveWorkbook.Worksheets("Valeurs").Cells(12, 1)
Here in the line col = Cells(1, 8).Value I access to the content of the worksheet which content I want to copy, and in the line newWorkBook1.Worksheets("Feuil1").Cells(1, 1).Value = "Stat" I access to the content of the "target" worksheet and I don't know how to refer to the content of the first worksheet in the following of the code in order to copy the content.
I hope I was clear, and I can add more precisions if necessary, sorry I don't master English so it's hard for me to explain the issue.
You can leave the Sub checkPVC_Click in the original workbook. Just ensure that you give full path and name of the file which has that macro. For example. Please ensure that the file from where you are running this macro is saved at least once.
Sub Sample()
Dim NewWorkbook As Workbook
Set NewWorkbook = Workbooks.Add
With NewWorkbook.Worksheets(1).Buttons
.Add 350, 15, 173.25, 41.25
.OnAction = "'" & ThisWorkbook.FullName & "'!checkPVC_Click"
End With
End Sub
Sub checkPVC_Click()
MsgBox "a"
End Sub
Regarding your Second question, you need to fully qualify the Cells object so that it know which cells are you referring to
ThisWorkbook will refer to the cell from the workbook which hosts the code.
Activeworkbook will refer to the cell from the workbook which is currently active.
Edit: Followup from comments. Is this what you are trying?
Sub Sample()
Dim newWorkBook As Workbook
Dim ws As Worksheet
Set newWorkBook = Workbooks.Add
Set ws = newWorkBook.Sheets(1)
ws.Name = "Valeurs"
With ws.Buttons
.Add 350, 15, 173.25, 41.25
.OnAction = "'" & ThisWorkbook.FullName & "'!checkPVC_Click"
End With
End Sub
Sub checkPVC_Click()
Dim OldWorkbook As Workbook, newWorkBook As Workbook
Dim createdSheetColumnsTab(100) As String
Set OldWorkbook = ActiveWorkbook
Set newWorkBook1 = Workbooks.Add
newWorkBook1.Worksheets("Feuil1").Cells(1, 1).Value = "Stat"
newWorkBook1.Worksheets("Feuil1").Cells(2, 1) = OldWorkbook.Worksheets("Valeurs").Cells(12, 1)
End Sub
To access the content of the first worksheet of workbook containing macro you need to use:
Thisworkbook.sheets(1).range("a1:a100") ' range as an example you can input anything
Hope it helped.

Finding a specific keyword in many workbooks along with a corresponding value and placing them in a column in one workbook

In a previous posting I asked about how to highlight a cell range that began with a certain keyphrase and ended when the next cell was blank. I would like to gain a better understanding of how to create a loop that performs this on multiple Excel files. Any help would be much appreciated. For reference, the code I am referring to is as follows:
Dim wk As Worksheet
Set wk = ActiveSheet
FirstRowColA = Application.WorksheetFunction.Match("keyphrase", wk.[A:A])
LastRowColA = Cells(wk.Rows.Count, "A").End(xlUp).Row
wk.Range("A" & FirstRowColA & ":A" & LastRowColA).Copy
Worksheets("Sheet2").Paste
In addition, I was curious about how to handle creating a "Sheet 2" if one does not exist already in the active workbook. Do I need to use something like Set WS = Sheets.Add and have Excel look at Worksheets(Sheets.Add).Paste?
I have also noticed that this code does not necessarily find what I am telling it to find, but this is an issue I should be able to resolve. For example, putting the phrase "Name" in the Match() function returns the text of a cell in column A containing a different word.
Let say u have excel files in the some folder
this code opens each workbook in the folder and searches specific string if found .copy and paste the required data.
Sub LoopThroughFiles()
Dim StrFile As String
Dim wk As Worksheet
StrFile = Dir("C:\Personal\Excel Report\*.xlsx")
Do While Len(StrFile) > 0
Workbooks.Open ("C:\Personal\Excel Report\" & StrFile)
Set wk = ActiveSheet
Set firstrowcola = activesheet.Range("A:A").Find("taskname") ' - search taskname in 1st row
If firstrowcola Is Nothing Then GoTo here:
LastRowColA = Cells(wk.Rows.Count, "A").End(xlUp).Row
wk.Range(firstrowcola.address & ":" & firstrowcola.offset(lastrowcola,0).address)).Copy
Set ws = Sheets.Add
ws.Range("A1").Select
ActiveSheet.Paste
here:
ActiveWorkbook.Close True
Loop
End Sub