How to use multiple for each loops simultaneously? - excel

Below code is used to run a macro that takes multiple variables and loops through the range to fill them into another sheet and then save as a pdf.
With 1 for each loop it works perfectly, but when I try to use 2; it will run through the first loop once and then loop through the second loop only.
Any ideas to fix this?
Sub CommandButton2_Click()
For Each c In Sheets("Resultaten").Range("N2:N1000").Cells '//Variable 1 range
If c = "" Then Exit For '//To end the loop when cells are empty
Sheets("Invuldocument").Range("B5").Value = c.Value '//Variable 1 transfer
For Each w In Sheets("Resultaten").Range("W2:W1000").Cells '//Variable 2 range
If w = "" Then Exit For '//To end the loop when cells are empty
Sheets("Invuldocument").Range("J5").Value = w.Value '//Variable 2 transfer
Application.Wait Now + #12:00:01 AM# ' //timer if the pc cannot handle the speed
Dim FileName As String '//Code below is to save as PDF in every loop
Dim Path As String
Application.DisplayAlerts = False
Path = "C:\Users\802435\Desktop\test12\"
FileName = "PRO-" & Range("B5").Value & "-" & Range("D41").Value & ".pdf"
ActiveWorkbook.SaveAs Path & FileName, xlOpenXMLWorkbook
Application.DisplayAlerts = True
Next '//Repeat for every Variable in the list until Exit For
Next '//No idea why i need this
End Sub

The idea is to loop through the row number then do a check if the value in both column N and W exist, if it does then it will copy the value to the 2 cells Invuldocument worksheet.
Sub CommandButton2_Click()
Const Path As String = "C:\Users\802435\Desktop\test12\" 'Assuming that the path don't change, you can declare it as a constant variable
Dim resultWS As Worksheet
Set resultWS = ActiveWorkbook.Worksheets("Resultaten")
Dim invulWS As Worksheet
Set invulWS = ActiveWorkbook.Worksheets("Invuldocument")
Dim i As Long
For i = 2 To 1000
If resultWS.Cells(i, "N").Value <> "" And resultWS.Cells(i, "W").Value <> "" Then
invulWS.Cells(5, "B").Value = resultWS.Cells(i, "N").Value
invulWS.Cells(5, "J").Value = resultWS.Cells(i, "W").Value
Dim FileName As String '//Code below is to save as PDF in every loop
Application.DisplayAlerts = False
FileName = "PRO-" & Range("B5").Value & "-" & Range("D41").Value & ".pdf"
ActiveWorkbook.SaveAs Path & FileName, xlOpenXMLWorkbook
Application.DisplayAlerts = True
Else
Exit For
End If
Next i
End Sub
Note: I did not test if the code for "saving as PDF" works as it is out of this question's scope. You are definitely encouraged to fully qualify your range reference in the code that assign FileName as it is currently referring to ActiveSheet which might not be what you want.

Related

Error message of Next without For being recieved

I've written a macro from parent file to change a child file.
The parent file has 10 + rows I want to cycle through.
The child file looks at row1 and creates a file based on the name in row 1.
I am then using a For and Next function to get the child to look at the next row and save the file based on the new name etc etc.
I get an error of:
Next without For
My code:
Sub CreateModels()
' set parameters
Dim vDestPath As String
Dim vDestFile As String
Dim vSrcePath As String
Dim vCurrFile As String
Dim vSrceFile As String
Dim vTot As Integer
vSrceFile = "Bridge 3-S Financial Model.xlsx"
vSrcePath = ActiveWorkbook.Path + "\Bridge 3-S Financial Model.xlsx"
vCurrFile = ActiveWorkbook.Name
vDestPath = ActiveWorkbook.Path & "\Output Models\"
'OpenFinancialModel
Workbooks.Open vSrcePath, UpdateLinks:=False
Sheets("Input Sheet Data").Select
Range("A4").Select
'creating models
For vTot = 6 To 1000
ActiveCell.FormulaR1C1 = "='[Input Sheet.xlsm]Input Sheet'!R" & vTot & "C1"
If Range("A4").Value <> 0 Then
Do
filepath = vDestPath & Range("a4") & ".Xlsx"
ActiveWorkbook.SaveAs (filepath)
vTot = vTot + 1
Next
Else
ActiveWorkbook.Close SaveChanges:=False
End If
End Sub
Remove the "Do" keyword and you might want to end the If statement before the "Next" keyword. Something like this:
For vtot = 6 To 1000
ActiveCell.FormulaR1C1 = "='[Input Sheet.xlsm]Input Sheet'!R" & vtot & "C1"
If Range("A4").Value <> 0 Then
filepath = vDestPath & Range("a4") & ".Xlsx"
ActiveWorkbook.SaveAs (filepath)
vtot = vtot + 1
Else
ActiveWorkbook.Close SaveChanges:=False
End If
Next
You need to improve your loops and queries. Half of the query If .. Then .. Else is within a For.. Next - not a good idea. Please check the position of Next and move to another place for your needs.
And there is an aborted Do missing some pseudo code like:
Dim k As Long
Do While k <= 10
Cells(k, 1).Value = k
Loop
Remove Do and debug your code.

VBA to copy pdf files from one location to another with progress bar

I have an imported CSV which will always put part numbers into Column B, the part drawing PDF is located in a central location.
I am trying to copy each drawing from one folder location to another, this part i have been successful with, however some of the files can have up to 3000 lines which means the copy sub can take some time to complete and may seem like excel is not functioning.
I have created a progress bar from some helpful tutorial, but i am struggling to combine them.
I understand the progress bar needs to calculate something in order to move the slider so i included a sub to count the number of unique entries in column B ( this would be the number of drawing which need copied ) The figure can then be used to create a percentage of completion?
Sub start()
UserForm1.Show
End Sub
Sub code()
Dim i As Integer, j As Integer, pctCompl As Single
'Sheet1.Cells.Clear
For i = 1 To 100
For j = 1 To 1000
Cells(i, 1).Value = j
Next j
pctCompl = i
progress pctCompl
Next i
End Sub
Sub progress(pctCompl As Single)
UserForm1.Text.Caption = pctCompl & "% Completed"
UserForm1.Bar.Width = pctCompl * 2
UserForm1.Caption = ListCount & "Files"
DoEvents
End Sub
Sub CountUniqueValues()
Dim LstRw As Long, Rng As Range, List As Object, ListCount As Long
LstRw = Cells(Rows.Count, "B").End(xlUp).Row
Set List = CreateObject("Scripting.Dictionary")
For Each Rng In Range("B2:B" & LstRw)
If Not List.Exists(Rng.Value) Then List.Add Rng.Value, Nothing
Next
ListCount = List.Count
End Sub
Sub PDFcopy()
Dim R As Range
Dim SourcePath As String, DestPath As String, FName As String
'Setup source and dest path (Note: must have a trailing backslash!)
SourcePath = "G:\test-copyfrom\" 'choose directory to copy from
DestPath = "C:\test-copyto\" 'choose directory to copy to
'Visit each used cell in column B
For Each R In Range("B1", Range("B" & Rows.Count).End(xlUp))
'Search the file with the file mask from the cell (Note: can contain wildcards like *.xls)
FName = Dir(SourcePath & R.Value & ".pdf")
'Loop while files found
Do While FName <> ""
'Copy the file
FileCopy SourcePath & FName, DestPath & FName
'Search the next file
FName = Dir()
Loop
Next
MsgBox ("files copied")
Here's how I code my progress bar
Sub progress(percentComplete As Single)
ProgressBar.Text.Caption = percentComplete & "% Completed"
ProgressBar.Bar.Width = percentComplete * 2
DoEvents
End Sub
And in my sub that does stuff:
'Update ProgressBar at certain points in the code
percentComplete = 11
progress percentComplete
Or
For each cell in Range("A1:A" & LRow)
'Do stuff
'Update ProgressBar in a loop
percentComplete = 11 + Int(cell.Row / LRow * 60) 'where 11 is the starting value, and 60 the percentage to be added
progress percentComplete
Next cell
This is to support my comment about using the progress bar
Dim f As UserForm1
Sub SetUpAProgressBar()
Set f = New UserForm1
f.Show vbModeless
f.ProgressBar1.Min = 0
f.ProgressBar1.Max = Range("a" & Rows.Count).End(xlUp).Row
f.ProgressBar1.Value = 0
End Sub
Sub IncrementProgressBar()
f.ProgressBar1.Value = f.ProgressBar1.Value + 1
End Sub
you need to add some sort of reference to your current row number in PDFcopy() sub. then count the total amount of loops to be completed. and finally, work out the percentage to pass to the progress bar!
Sub PDFcopy()
Dim R As Range
Dim I as long
Dim Total as long
Dim SourcePath As String, DestPath As String, FName As String
'Setup source and dest path (Note: must have a trailing backslash!)
SourcePath = "G:\test-copyfrom\" 'choose directory to copy from
DestPath = "C:\test-copyto\" 'choose directory to copy to
'Visit each used cell in column B
I = 0
Total = Range("B" & Rows.Count).End(xlUp)
For Each R In Range("B1", Range("B" & Rows.Count).End(xlUp))
'Search the file with the file mask from the cell (Note: can contain wildcards like *.xls)
FName = Dir(SourcePath & R.Value & ".pdf")
'Loop while files found
Do While FName <> ""
'Copy the file
FileCopy SourcePath & FName, DestPath & FName
'Search the next file
FName = Dir()
Loop
I = I + 1
call progress(I/(total/100))
Next
MsgBox ("files copied")

Update named cell values

I have a workbook with many named cells in different worksheets. I'm trying to write a VBA script that will read an external .csv file to extract a variable name and variable value, so that I can update the named cell values in my workbook.
I'm able to read and loop through the data in the CSV file but I am unable to update the named values.
Ideally, the script would check the variable name is a valid named cell in the workbook then update with the new value as defined in the .csv file.
I've run a number of iterations but the gist of the code is:
Public Sub readCSV()
'
' VBA script to read external CSV file
'
'
Dim filePath As String
Dim inFilePath As String
Dim inCase As String
strWorkBook = ActiveWorkbook.Name
filePath = Range("aString").Value
tmpsep = InStrRev(filePath, "\")
inCase = Right(filePath, Len(filePath) - tmpsep)
inFilePath = Left(filePath, Len(filePath) - Len(inCase))
' Check that path is valid and exit if not
Range("aString").Select
If IsEmpty(ActiveCell.Value) Then
MsgBox "ERROR! No Input File Defined - Exiting!"
Range("H7").Select
End
End If
' Open data file
Workbooks.Open Filename:=filePath
' Loop through variable names in input file
varNamCol = "C"
varColNum = "D"
' Ensure we're in input file
Windows(inCase).Activate
' Find last row input file - Call separate routine (working)
Call FindLastRow.FindLastRow(lRow)
i = 1
imax = lRow
Do While i <= imax
Windows(inCase).Activate
' Read Variable Name and Value from csv
inVarName = Range(varNamCol & I).Value
inVarValue = Range(varColNum & I).Value
If IsEmpty(inVarName) Then
MsgBox " Variable is empty - Moving On"
GoTo NextIteration
Else
Windows(strWorkBook).Activate
Range(inVarName).Value = inVarValue
End If
NextIteration:
i = i + 1
Loop
End Sub
Issue resolved by performing the operations the other way around. Instead of reading the input deck and trying to find the corresponding named range in the target workbook, I loop through the named ranges and find the corresponding values from the input deck.
I have also included the Application.EnableEvents commands to prevent embedded Worksheet_Change macros from activating while updating values.
The code is:
Sub tmp()
Dim filePath As String
Dim inFilePath As String
Dim inCase As String
On Error GoTo ErrorHandler
Application.ScreenUpdating = False
Application.EnableEvents = False
'----------------------------------
' Find path for input file
strWorkBook = ActiveWorkbook.Name
filePath = Range("aString").Value
tmpsep = InStrRev(filePath, "\")
' Input file workbook name
inCase = Right(filePath, Len(filePath) - tmpsep)
'Input file full path
inFilePath = Left(filePath, Len(filePath) - Len(inCase))
' Check that path is valid and exit if not
Range("aString").Select
If IsEmpty(ActiveCell.Value) Then
MsgBox "ERROR! No Input File Defined - Exiting!"
Range("H7").Select
End
End If
' Open input data file
Workbooks.Open Filename:=filePath
'-------------------------------------
Dim rFind As Range
' Process to update name values
Windows(strWorkBook).Activate
For Each nm In ActiveWorkbook.Names
varname = nm.Name
varsheet = Range(nm).Parent.Name
varcell = nm.RefersToRange.Address(False, False)
Sheets(varsheet).Select
Range(varcell).Select
' Ensure variable in Home and HiddenVariables are not over-written
If varsheet = "Home" Or varsheet = "HiddenVariables" Then
GoTo NextIteration
End If
' Omit non-user input variables cbelts, anrz, anumhxc, nrotzone
If varname = "cbelts" Or varname = "anrz" Or varname = "anumhxc" Or varname = "nrotzone" Then
GoTo NextIteration
End If
' Selection.ClearContents
Windows(inCase).Activate
' Find range in inCase that matched varName
With Range("C:C")
Set rFind = .Find(What:=varname, LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not rFind Is Nothing Then
inCaseRow = rFind.Row
updateVal = Range("D" & inCaseRow).Value
Windows(strWorkBook).Activate
Sheets(varsheet).Select
Range(varcell).Value = updateVal
Range("D4").Select
Else
Windows(strWorkBook).Activate
Range("D4").Select
End If
End With
NextIteration:
Next nm
' Include routines to populate Porous Media inputs
Application.ScreenUpdating = True
' Close input case file
Windows(inCase).Activate
ActiveWindow.Close
ErrorHandler:
Application.EnableEvents = True
End Sub

object required run time error '424'

i am getting object required run time error in below code at line , i checked sheet names they are correct but still showing same error Sheet1.Range("A1").Value = Date & " " & Time
Private Sub CommandButton1_Click()
Dim username As String
Dim password As String
username = TextBox1.Text
password = TextBox2.Text
Dim info
info = IsWorkBookOpen("D:\TMS_Project\username-password.xlsx")
If info = False Then
Workbooks.Open ("D:\TMS_Project\username-password.xlsx")
End If
Dim x As Integer
x = 2
Do While Cells(x, 1).Value <> ""
If Cells(x, 1).Value = username And Cells(x, 2).Value = password Then
MsgBox "Welcome!"
Sheet1.Range("A1").Value = Date & " " & Time
Selection.NumberFormat = "m/d/yyyy h:mm AM/PM"
UserForm1.Hide
ActiveWorkbook.Close True
End
Else
x = x + 1
End If
Loop
MsgBox "Please check your username or password!"
ActiveWorkbook.Close True
TextBox1.Text = ""
TextBox2.Text = ""
TextBox1.SetFocus
End Sub
When you use Sheet1.Range("A1").Value, Sheet1 is actually the Worksheet.CodeName property, read here on MSDN.
While I think you meant to use the worksheet, which name is "Sheet1", then you need to use Worksheets("Sheet1").Range("A1").Value.
If you would have defined and set your Worksheet object, you would have been able to track it.
I am using the piece of code below, to verify that no one has changed my sheet's name (or deleted it).
Option Explicit
' list of worksheet names inside Workbook - easy to modify here later
Const ShtName As String = "Sheet1"
'====================================================================
Sub VerifySheetObject()
Dim Sht As Worksheet
On Error Resume Next
Set Sht = ThisWorkbook.Worksheets(ShtName)
On Error GoTo 0
If Sht Is Nothing Then ' in case someone renamed the Sheet (or it doesn't exist)
MsgBox "Sheet has been renamed, it should be " & Chr(34) & ShtName & Chr(34), vbCritical
Exit Sub
End If
' your line here
Sht.Range("A1").Value = Date & " " & Time
End Sub
To use Variables for your Sheets use:
Dim sht as Worksheet
Set sht = Worksheets("Name")
If you are refering a lot to worksheets its a must to use, but also makes it much easier to change later on.

How to populate data from .txt file into Excel in VBA?

I'm trying to create something to read data from a .txt file, then populate data into .xls, but after open the .txt file, how do I get the data out? Basically I'm trying to get the the third column of the lines dated '04/06/2010'. After I open the .txt file, when I use ActiveSheet.Cells(row, col), the ActiveSheet is not pointing to .txt file.
My .txt file is like this (space delimited):
04/05/10 23 29226
04/05/10 24 26942
04/06/10 1 23166
04/06/10 2 22072
04/06/10 3 21583
04/06/10 4 21390
Here is the code I have:
Dim BidDate As Date
BidDate = '4/6/2010'
Workbooks.OpenText Filename:=ForecastFile, StartRow:=1, DataType:=xlDelimited, Space:=True
If Err.Number = 1004 Then
MsgBox ("The forecast file " & ForecastFile & " was not found.")
Exit Sub
End If
On Error GoTo 0
Dim row As Integer, col As Integer
row = 1
col = 1
cell_value = activeSheet.Cells(row, col)
MsgBox ("the cell_value=" & cell_value)
Do While (cell_value <> BidDate) And (cell_value <> "")
row = row + 1
cell_value = activeSheet.Cells(row, col)
' MsgBox ("the value is " & cell_value)
Loop
If cell_value = "" Then
MsgBox ("A load forecast for " & BidDate & " was not found in your current load forecast file titled '" + ForecastFile + ". " + "Make sure you have a load forecast for the current bid date and then open this spreadsheet again.")
ActiveWindow.Close
Exit Sub
End If
Can anyone point out where it goes wrong here?
In the example below, I set the variable ws equal to the sheet I want and I'm able to use that variable to refer to the sheet later. The keyword ActiveWorkbook should point to the newly opened text file. I could tell what you wanted to do with the info, such I just made some stuff up.
Sub GetBidData()
Dim dtBid As Date
Dim ws As Worksheet
Dim rFound As Range
Dim sFile As String
dtBid = #4/6/2010#
sFile = Environ("USERPROFILE") & "\My Documents\ForecastFile.txt"
Workbooks.OpenText Filename:=sFile, _
StartRow:=1, _
DataType:=xlDelimited, _
Space:=True
Set ws = ActiveWorkbook.Sheets(1)
Set rFound = ws.Columns(1).Find( _
Format(dtBid, ws.Range("A1").NumberFormat), , xlValues, xlWhole)
If Not rFound Is Nothing Then
MsgBox rFound.Value & vbCrLf & _
rFound.Offset(0, 1).Value & vbCrLf & _
rFound.Offset(0, 2).Value
End If
End Sub
You should generally avoid using the ActiveWorkbook object unless you're positive that the workbook you want to reference will always be active when your code is run. Instead, you should set the workbook you're working with to a variable. Theoretically, you should be able to use the OpenText method to do this, but VBA doesn't like that. (I'm pretty sure it's a bug.) So right after you open your text file, I would do this:
Workbooks.OpenText Filename:=Forecastfile, StartRow:=1,
DataType:=xlDelimited, Space:=True
Dim ForecastWorkbook As Workbook, book As Workbook
Dim ForecastFileName As String
ForecastFileName = "YourFileNameHere.txt"
For Each book In Application.Workbooks
If book.Name = ForecastFileName Then
Set ForecastWorkbook = book
Exit For
End If
Next book
Then, instead of this...
cell_value = activeSheet.Cells(row, col)
...do this...
cell_value = ForecastWorkbook.Sheets(1).Cells(row, col).Value
Below code will read the text file and paste the values in the cell of Sheet2. However if you put a formatting in the Date column that will do the trick
Public Sub Read_text()
Sheet2.Activate
Set fso = New FileSystemObject
Fname = Application.GetOpenFilename
x = 1
y = 1
Set Stream = fso.OpenTextFile(Fname, ForReading, True)
Do While Not Stream.AtEndOfStream
Str_text = Stream.ReadLine 'Perform your actions
rdtext = Split(Str_text, " ")
Sheet2.Cells(x, y) = rdtext(0)
Sheet2.Cells(x, y + 1) = rdtext(1)
Sheet2.Cells(x, y + 2) = rdtext(2)
x = x + 1
y = 1
Loop
Stream.Close
End Sub
For example : Below code will change the format in '05/04/2010'
Sheet2.Cells(x, y) = Format(rdtext(0), "mm/dd/yyyy;#")

Resources