Nested If Then and For Statements - vba

I know how to fix the error in the macro below, but not the why behind the fix. Why is the " _" causing problems in the second If...Then statement?
I can fix it by either deleting the " _" or inserting a line below it. However, I can't move the For Statement to the end of the If...Then statement.
Sub Loop_Link_Change_ROE()
Dim MyPath As String
Dim MyFile As String
Dim sLink As String
Dim sNewName As String
Dim tNewName As String
Dim varLinks As Variant
Dim i As Integer
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.EnableEvents = False
MyPath = "P:\Department\Actuarial Archive\Reserves\2018Q2\Documentation\Data Recon\"
MyFile = Dir(MyPath)
Do While MyFile <> ""
If MyFile Like "*Analysis_Regions_Phys_CM_*.xl*" Then
Workbooks.Open Filename:=MyPath & MyFile, UpdateLinks:=0
varLinks = ActiveWorkbook.LinkSources(xlExcelLinks)
If Not IsEmpty(varLinks) Then _
For i = 1 To UBound(varLinks)
If InStr(1, varLinks(i), "4Q17") Then sNewName = Replace(varLinks(i), "4Q17", "2Q18")
If InStr(1, varLinks(i), "GA") Then tNewName = Replace(sNewName, "GA", "Mid(varLinks(i), 30, 2)")
If InStr(1, varLinks(i), "GA") Then ActiveWorkbook.ChangeLink Name:=varLinks(i), NewName:=tNewName, Type:=xlExcelLinks
ActiveWorkbook.Close True
Next
End If
End If
MyFile = Dir
Loop
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.EnableEvents = True
End Sub
Thanks in advance for any help!

There are two basic forms using If in VBA
All one one line:
If {test} Then {something}
...in which case subsequent lines have no connection with the If
Using End If and multiple lines:
If {test} Then
{something} 'one or more lines of code
End If
Your _ is not doing anything useful there

Underscore is a line continuation in vb so if you use it then you do not need an "end if" for that if statement because the for loop line below is treated as if it were part of the previous line.

Related

Autofilter loop using array

I am having trouble debugging my code. I have an array with the criterial of an autofilter column. My code is supposed to loop through the array, open a set of files and copy-paste information into my workbook.
When I run the code it does not autofiler to the desired criterial and shows a Run-time error 1004. I already tried searching for solutions or similar problems, but found nothing. I also tried recording a macro to change the approach, but when trying to implement the loop it does not work :(
Any help is appreaciated!
Sub Update_Database()
Dim directory As String
Dim fileName As String
Dim my_array() As String
Dim iLoop As Integer
ReDim my_array(18)
my_array(0) = "Aneng"
my_array(1) = "Bayswater"
my_array(2) = "Bad Blankenburg"
my_array(3) = "Halstead"
my_array(4) = "Jorf Lasfar"
my_array(5) = "Kolkatta"
my_array(6) = "Marysville"
my_array(7) = "Northeim"
my_array(8) = "Ponta Grossa"
my_array(9) = "Puchov"
my_array(10) = "Renca"
my_array(11) = "Padre Hurtado"
my_array(12) = "Shanxi"
my_array(13) = "San Luis Potosi"
my_array(14) = "Szeged"
my_array(15) = "Tampere"
my_array(16) = "Uitenhage"
my_array(17) = "Veliki Crljeni"
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
.Show
directory = .SelectedItems(1)
Err.Clear
End With
fileName = Dir(directory & "\", vbReadOnly)
Dim mwb As Workbook
Set mwb = Workbooks("OEE_Database_Final.xlsm")
Do While fileName <> ""
For iLoop = LBound(my_array) To UBound(my_array)
On erro GoTo ProcExit
With Workbooks.Open(fileName:=directory & "\" & fileName, UpdateLinks:=False, ReadOnly:=True)
Selection.AutoFilter Field:=1, Criterial:=my_array(iLoop)
mwb.Worksheets(8).Range("O9:Z2945") = .Worksheets(8).Range("O9:Z2945").Value2
.Close SaveChanges:=False
End With
fileName = Dir
Next iLoop
Loop
ActiveSheet.ShowAllData
ProcExit:
Exit Sub
End Sub

VBA Convert from text to excel Format cells change from General to numeric for some rows

I have code which compares two folders (textFiles & ExcelFiles), to find if all textFiles are converted to Excel. If not, it calls a function that does this. Everything works well, but when I open the Excel file, the format may change from a row to another in the same column.
This is my code:
Sub LookForNew()
Dim dTxt As String, dExcel As String, key As String
Dim i As Integer
Dim oFileExcel, tFileExl, oFileExl, fso, filsTxt, filsExcel, fil, exl
Set fso = CreateObject("Scripting.FileSystemObject")
Set filsTxt = fso.GetFolder("C:\txtFiles").Files
Set filsExcel = fso.GetFolder("C:\excelFiles").Files
Set oFileExcel = CreateObject("Scripting.Dictionary")
Set tFileExl = CreateObject("Scripting.Dictionary")
Set oFileExl = CreateObject("Scripting.Dictionary")
i = 0
For Each fil In filsTxt
dTxt = fil.Name
dTxt = Left(dTxt, InStr(dTxt, ".") - 1)
For Each exl In filsExcel
dExcel = exl.Name
dExcel = Left(dExcel, InStr(dExcel, ".") - 1)
key = CStr(i)
oFileExcel.Add dExcel, "key"
i = i + 1
Next exl
If Not (oFileExcel.Exists(dTxt)) Then
Call tgr
End If
Next fil
Set fso = Nothing
End Sub
Sub tgr()
Const txtFldrPath As String = "C:\txtFiles"
Const xlsFldrPath As String = "C:\excelFiles"
Dim CurrentFile As String: CurrentFile = Dir(txtFldrPath & "\" & "*.txt")
Dim strLine() As String
Dim LineIndex As Long
Application.ScreenUpdating = False
Application.DisplayAlerts = False
While CurrentFile <> vbNullString
LineIndex = 0
Close #1
Open txtFldrPath & "\" & CurrentFile For Input As #1
While Not EOF(1)
LineIndex = LineIndex + 1
ReDim Preserve strLine(1 To LineIndex)
Line Input #1, strLine(LineIndex)
'STRIP TABS OUT AND REPLACE WITH A SPACE!!!!!
strLine(LineIndex) = Replace(strLine(LineIndex), Chr(9), Chr(32))
Wend
Close #1
With ActiveSheet.Range("A1").Resize(LineIndex, 1)
.Value = WorksheetFunction.Transpose(strLine)
'DEFINE THE OPERATION FULLY!!!!
.TextToColumns Destination:=.Cells(1), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, _
Tab:=False, Semicolon:=False, Comma:=False, Space:=False, _
Other:=True, OtherChar:="|"
End With
ActiveSheet.UsedRange.EntireColumn.AutoFit
ActiveSheet.Copy
ActiveWorkbook.SaveAs xlsFldrPath & "\" & Replace(CurrentFile, ".txt", ".xlsx"), xlOpenXMLWorkbook
ActiveWorkbook.Close False
ActiveSheet.UsedRange.ClearContents
CurrentFile = Dir
Wend
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
This is the picture:
The General format cell changes for some records and becomes a number exp: 4'927'027.00 should be 4927027 like the others.
this is the text file lines
And I want to put a msgBox when there's no Files to convert in "LookForNew" function, but I don't know where.
Question 1: I open the Excel file, the format may change from a row to another in the same column.
Answer: The problem probable lies in your text file. Note what row ,column, and value that isn't formatted properly. Next go to that line and column in your text file. You'll most likely see 4,927,027 or "4927027". In either case Excel might mistake it for a string value.
Question 2: I want to put a msgBox when there's no Files to convert in "LookForNew" function, but I don't know where.
Put a counter in your If Files Exist. You should have your MsgBox after you exit your file loop. - Next fil
This line is miss leading:
oFileExcel.Add dExcel, "key"
correct syntax
dictionary.add key, value
Keys are unique identifiers. Before you add a key to a dictionary you should test to see if the key exist
If not oFileExcel.Exists dExcel then oFileExcel.Add dExcel, ""
Values are references to objects or values.
This line adds the exl file object to oFileExcel dictionary
If not oFileExcel.Exists dExcel then oFileExcel.Add dExcel, exl
This line retrieves the value
Set exl = oFileExcel("SomeKey")
The error is being thrown because you are adding the same key twice. The key values are the name of the Excel file without an extension. Example.xls and Example.xlsx will produce the same key.
That being said, there is no need to use a dictionary. Or to do a file loop in tgr().
I better approach would be
Sub Main
For each textfile
basename = get text file basename
xlfile = xlFileDirectory + baseFileName + excel file extension
if not xlfile Exists then call CreateExcelFromTxt f.Path, xlFileName
End Sub
Sub CreateExcelFromTxt( txtFile, xlFileName)
Open txtFile
Build strLine
Create Excel -> xlFileName
Add strLine to xlFileName
run TextToColumns
End Sub
Here is a starter template
Sub LookForNew()
Const xlFileDirectory = "C:\excelFiles\"
Const txtFileDirectory = C:\txtFiles\"
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Dim fso, fld , f, xlFileName
Set fso = WScript.CreateObject("Scripting.Filesystemobject")
Set fld = fso.GetFolder(txtFileDirectory)
Set txtFiles = fso.GetFolder(txtFileDirectory).Files
For Each f In txtFiles
baseFileName = Left(f.Name,InStrRev(f.Name,".")-1)
xlFilePath = xlFileDirectory & baseFileName & ".xlsx"
If Not fso.FileExists(xlFilePath ) Then CreateExcelFromText f.Path, xlFileName
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Sub CreateExcelFromText(txtFileName, xlFileName)
End Sub

Merge Cells with Duplicate Data VBA

I'm trying to get a Macro working to merge cells with duplicate data. It will work on small numbers of cells, but I get the following error if I try to run it on a larger group of cells. I'm not sure if there's a more efficient way for excel to run through this.
Run-Time error '1004':
Method 'Range' of object '_Global' failed
Here's the code:
Sub MergeDuplicates()
Dim varData As Variant, varContent As Variant
Dim strMyRange As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False
strMyRange = ActiveCell.Address
varContent = ActiveCell.Value
For Each varData In Selection.Cells
If varData.Value <> varContent Then
strMyRange = strMyRange & ":" & Cells(varData.Row - 1, varData.Column).Address & ", " & Cells(varData.Row, varData.Column).Address
varContent = Cells(varData.Row, varData.Column).Value
End If
Next
strMyRange = strMyRange & Mid(Selection.Address, InStr(1, Selection.Address, ":"), Len(Selection.Address))
Range(strMyRange).Merge
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
I have recreated the issue using the code you posted and it is working for me. I did what you suggested and put the merge into the For loop. Then I split strMyRange using the comma as the delimiter. I set up a test to look for the ":" character in TestArray(0). If it is in that target string, then I know it is ready for the merge. After that I reset strMyRange to the TestArray(1) which is the beginning of the next range.
Note: I was able to step through it with the debugger with 100 cells and it worked. Then I tried running it without any code breakpoints, but it merged all the selected cells. I put a 1 second wait statement right before the final merge and that seems to work.
Here is the code:
Sub MergeDuplicates()
Dim varData As Variant, varContent As Variant
Dim strMyRange As String
Dim TestArray() As String
Dim target As String
Dim pos As Integer
Application.ScreenUpdating = False
Application.DisplayAlerts = False
strMyRange = ActiveCell.Address
varContent = ActiveCell.Value
For Each varData In Selection.Cells
If varData.Value <> varContent Then
strMyRange = strMyRange & ":" & Cells(varData.Row - 1, varData.Column).Address & ", " & Cells(varData.Row, varData.Column).Address
TestArray = Split(strMyRange, ",")
target = TestArray(0)
pos = InStr(target, ":")
If (pos > 0) Then
Range(target).Merge
strMyRange = TestArray(1)
End If
varContent = Cells(varData.Row, varData.Column).Value
End If
Next
strMyRange = strMyRange & Mid(Selection.Address, InStr(1, Selection.Address, ":"), Len(Selection.Address))
Application.Wait (Now + #12:00:01 AM#) 'This helps the application run OK if there are no breakpoints.
Range(strMyRange).Merge
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub

VBA search and replace with wildcards: using \ (backslash) in replace string also containing numbers (error: 5623)

Premiss:
I have a word document with a lot of { LINKS ... } to an excel document to be able to generate word documents easier. When i move these documents to a new directory i want to update all links with the new dir and possibly a new excel docname as well.
Problem:
I have found on stackoverflow and other sites a vba/macro that mostly does what i need. The problem arises when i do a wildcard .find .replace where the replace text contains \ and the dirname has numbers.
Code:
Public Sub planer_fix_data_link()
Dim rngStory As Word.Range
Dim pFindTxt As String
Dim pReplaceTxt As String
Dim lngJunk As Long
Dim oShp As Shape
'Pattern to find with wildcards as i don't always know the last location
pFindTxt = "LINK Excel.Sheet.12*xlsx"
TryAgain:
pReplaceTxt = InputBox("New excel filename", "Malldata filnamn")
If pReplaceTxt = "" Then
If MsgBox("Do you just want to delete the found text?", vbYesNoCancel) = vbNo Then
GoTo TryAgain
ElseIf vbCancel Then
MsgBox "Cancelled by User."
Exit Sub
End If
End If
currPath = ActiveDocument.Path
'links need double for some reason
currPath = Replace(currPath, "\","\\")
'text to replace with
pReplaceTxt = "LINK Excel.Sheet.12 """ & currPath & "\\" & pReplaceTxt & ".xlsx"
Application.ActiveWindow.View.ShowFieldCodes = True
'Fix the skipped blank Header/Footer problem
lngJunk = ActiveDocument.Sections(1).Headers(1).Range.StoryType
'Iterate through all story types in the current document
For Each rngStory In ActiveDocument.StoryRanges
'Iterate through all linked stories
Do
SearchAndReplaceInStory rngStory, pFindTxt, pReplaceTxt
On Error Resume Next
Select Case rngStory.StoryType
Case 6, 7, 8, 9, 10, 11
If rngStory.ShapeRange.Count > 0 Then
For Each oShp In rngStory.ShapeRange
If oShp.TextFrame.HasText Then
SearchAndReplaceInStory oShp.TextFrame.TextRange, pFindTxt, pReplaceTxt
End If
Next
End If
Case Else
'Do Nothing
End Select
On Error GoTo 0
'Get next linked story (if any)
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
Application.ActiveWindow.View.ShowFieldCodes = False
ActiveDocument.Fields.Update
End Sub
Public Sub SearchAndReplaceInStory(ByVal rngStory As Word.Range, ByVal strSearch As String, ByVal strReplace As String)
With rngStory.Find
.ClearFormatting
'.Replacement.ClearFormatting
.MatchWildcards = True
.Text = strSearch
.Replacement.Text = strReplace
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
End Sub
current dir is something like C:\Users\\Dropbox\Project\1. planning\\
Easy reproduction
as my code uses the same engine as the standard search and replace one can easily reproduce the problem by starting a new word doc typing in
C:\\Users\\testuser\\Dropbox\\Project\\test\\testproject\\excelfile.xlsm
And the do a wildcard search and replace with
C:*.xlsm
as search and
C:\\Users\\testuser\\Dropbox\\Project\\1. Planning\\testproject\\excelfile.xlsm
as replace
I figure i need some way of escaping my backslashes but i just cant find a way to do that
Okay this gets a little more complex you need to replace the backslashes with the ascii eqivalent ^92. However as you have numbers as well then they become a problem if they follow a \ so need converting to ascii as well.
So use a function to convert the replacement string to the correct format like below
Function convert(inp As String) As String
Dim ret As String
Dim char As String
ret = ""
For i = 1 To Len(inp)
char = Mid(inp, i, 1)
If char = "\" Or (char >= "0" And char <= "9") Then
ret = ret + "^" + Format(Asc(char))
Else
ret = ret + char
End If
Next i
convert = ret
End Function

type mismatch when pulling .value from workbook

I'm trying to set up the dashboard I just created to automatically(well, as soon as it gets opened again) update itself as I make changes in the future. I've worked out the following method of doing it, but I keep getting a 'Type Mismatch' error on the line marked with **. I feel like I"m missing something pretty obvious here, but for the life of me, I can't figure it out. Any ideas?
Private Sub Workbook_Open()
Dim UpDateBook As Workbook
Dim CurrVer As String
Dim AdminFile As String
Dim AdminFolder As String
Dim MyPath As String
''Change the next two according to where the admin file will be located.
AdminFile = "\\dallfile\Databases\Reports\Dashboard\Dashboard Update.xlsx"
AdminFolder = "\\dallfile\Databases\Reports\Dashboard"
MyPath = ThisWorkbook.Path
MyPath = MyPath & "\"
Application.ScreenUpdating = False
Set UpDateBook = Workbooks.Open(AdminFile, , True)
**CurrVer = Workbooks(UpDateBook).Sheets("Version_Log").Range("A5000").End(xlUp).Value
CurrVer = CurrVer & ".xlsm"
If ThisWorkbook.Name <> CurrVer Then
MsgBox ("There is a new update for your file available. It will be loaded as soon as you press OK")
Workbooks.Open Filename:=AdminFolder & CurrVer
Application.EnableEvents = False
Workbooks(CurrVer).SaveAs Filename:=MyPath & CurrVer, FileFormat:=xlNormal
Application.EnableEvents = True
With ThisWorkbook
.Saved = True
.ChangeFileAccess Mode:=xlReadOnly
Kill pathname:=.FullName
.Close savechanges:=False
End With
End If
Application.ScreenUpdating = True
End Sub
I think this is because you are using your workbook object incorrectly.
You set the workbook here..
Set UpDateBook = Workbooks.Open(AdminFile, , True)
and then you should use it like this.
CurrVer = UpDateBook.Sheets("Version_Log").Range("A5000").End(xlUp).Value
Just a matter of syntax. Once you have:
Set UpDateBook = Workbooks.Open(AdminFile, , True)
You should use it like:
CurrVer = UpDateBook.Sheets("Version_Log").Range("A5000").End(xlUp).Value