Unable to use variable input - excel

Background
As I am trying to run a set of technical indicators on a large number of csv data files, I patched together a 3 macros which was intended to
Macro 1: RunAnalysis > Open every individual excel file in specific
folder
Macro 2: DoWork > Run Macro Macro 3: IndicatorData > To
populate the individual csv files opened by Macro 1 with technical
indicator formulas.
The codes are found below.
Problem/Issue
The problem lies with Macro 3 [Indicator Data]
The value of variable EMAWindow1 which captures a value from the sheet called ControlPanel found in the same Workbook is used selectively by vba when populating column H.
In the first two lines of formulas
ActiveSheet.Range("h1") = EMAWindow1 & " Day EMA"
ActiveSheet.Range("h" & EMAWindow1 + 1) = "=average(R[-" & EMAWindow1 - 1 & "]C[-3]:RC[-3])"
You will find the macro working perfecting. However
When you reach the third line
ActiveSheet.Range("h" & EMAWindow1 + 2 & ":h" & LastRowCheck).FormulaR1C1 = "=R[0]C[-3]*(2/(EMAWindow1 + 1)) + R[-1]C[0] * (1-(2/(EMAWindow1 + 1)))"
For some reason, the value of EMAWindow1 is not used and is treated as a text causing error and resulting in the #NAME? as the formula is unable to calculate with a text inside it.
The subsequent codes encounter the same problem. Anyone faced the same problem before? I have been at this problem for awhile, and I hope for some enlightenment.
Codes
Sub RunAnalysis()
Dim Filename, Pathname As String
Dim wb As Workbook
Pathname = "C:\Users\gabri_000\Desktop\Trading Data\Stocks - 1 - 100\"
Filename = Dir(Pathname & "*.csv")
Do While Filename <> ""
Set wb = Workbooks.Open(Pathname & Filename)
DoWork wb
wb.Close SaveChanges:=True
Filename = Dir()
Loop
End Sub
Sub DoWork(wb As Workbook)
With wb
Call IndicatorData
End With
End Sub
Sub IndicatorData()
Dim LastRowCheck As Long
Dim EMAWindow1, EMAWindow2, EMAWindow3 As Long
Dim Pathname, Filename, FileNameIndex, FinalFileName As String
'Converting file path into a string
Pathname = "C:\Users\gabri_000\Desktop\Trading Data\Stocks - 1 - 100\"
'Full file name
Filename = Dir(Pathname)
'Removing the .csv portion of the file name
FileNameIndex = InStr(1, Filename, ".csv")
FinalFileName = Left(Filename, FileNameIndex - 1)
'Selecting Recently Opened File
Sheets(FinalFileName).Select
'Counting Number of Rows in the worksheet
With Worksheets(FinalFileName)
LastRowCheck = .Range("A" & .Rows.Count).End(xlUp).Row
End With
'EMA Inputs
'Obtaining data from masterfile
With ThisWorkbook.Sheets("ControlPanel")
EMAWindow1 = .Range("EMAWindow1")
EMAWindow2 = .Range("EMAWindow2")
EMAWindow3 = .Range("EMAWindow3")
End With
'EMA Calcuations
ActiveSheet.Range("h1") = EMAWindow1 & " Day EMA"
ActiveSheet.Range("h" & EMAWindow1 + 1) = "=average(R[-" & EMAWindow1 - 1 & "]C[-3]:RC[-3])"
ActiveSheet.Range("h" & EMAWindow1 + 2 & ":h" & LastRowCheck).FormulaR1C1 = "=R[0]C[-3]*(2/(EMAWindow1 + 1)) + R[-1]C[0] * (1-(2/(EMAWindow1 + 1)))"
ActiveSheet.Range("i1") = EMAWindow2 & " Day EMA"
ActiveSheet.Range("i" & EMAWindow2 + 1) = "=average(R[-" & EMAWindow2 - 1 & "]C[-4]:RC[-4])"
ActiveSheet.Range("i" & EMAWindow2 + 2 & ":i" & LastRowCheck).FormulaR1C1 = "=R[0]C[-4]*(2/(EMAWindow2 + 1)) + R[-1]C[0] * (1-(2/(EMAWindow2 + 1)))"
ActiveSheet.Range("j1") = EMAWindow3 & " Day EMA"
ActiveSheet.Range("j" & EMAWindow3 + 1) = "=average(R[-" & EMAWindow3 - 1 & "]C[-5]:RC[-5])"
ActiveSheet.Range("j" & EMAWindow3 + 2 & ":i" & LastRowCheck).FormulaR1C1 = "=R[0]C[-5]*(2/(EMAWindow3 + 1)) + R[-1]C[0] * (1-(2/(EMAWindow3 + 1)))"
End Sub

Related

I want to format my csv file, from an excel export

I have a problem with the date format in the new exported csv file.
If I export a range from an excel file, then the date format is dd/mm/yyyy but i need dd/mm/yyyy hh:nn.
If I changed the format in the original excel file to the right form, then the most values in the csv show the right format except the date-value e.g. 18.08.2021 00:00.
So if the time is 00:00 then only the dd/mm/yyyy format appears at that row and this format is incompatible to the database.
(i opened it in excel and in the editor and it appeared the same problem)
can someone help me?
Dim ws As Worksheet, fd As FileDialog, rngTest As Range, rngExport As Range, fltr As FileDialogFilter
Dim start As Long
start = 2
'Nach jeweiliger Zeit wird Datenreihe (start ab) ausgewählt
If Time < TimeValue("11:15") Then
Do Until Daten.Range("ov" & start) = Date + 1
start = start + 1
Loop
ElseIf Time < TimeValue("11:15") Then
Do Until Daten.Range("ov" & start) = Date + 2
start = start + 1
Loop
Else: start = 2
End If
start = start + 1
'Worksheet auf dem die Daten stehen
Set ws = Worksheets("Daten")
'Zelle die auf Inhalt überprüft werden soll
Set rngTest = ws.Range("ov2")
'Bereich der exportiert wird
Set rngExport = ws.Range("ov" & start & ":ow10000")
' ws.Range("ov" & start & ":ov5000").NumberFormat = "dd/mm/yyyy hh:mm"
If rngTest.Text <> "" Then
Set fd = Application.FileDialog(msoFileDialogSaveAs)
'Filename
fd.InitialFileName = "LG" & " " & Diagramm.Range("a5").Value & " " & "RZ" & " " & Format(Date, "mmmm") & " " & Format(Date, "yyyy") & "_" & "MW" & "_" & "ab" & " " & Daten.Range("ov" & start - 1).Value
' Application.Dialogs(xlDialogSaveAs).Show filenameComplete
With fd
.Title = ""
'Filterindex für CSV-Dateien ermitteln
For i = 1 To .Filters.count
If .Filters(i).Extensions = "*.csv" Then
.FilterIndex = i
Exit For
End If
Next
'Wenn OK geklickt wurde starte Export
If .Show = True Then
ExportRangeAsCSV rngExport, ";", .SelectedItems(1)
End If
End With
End If
End Sub
'Hier werden die Werte in eine CSV-Datei eingefügt und gespeichert
Sub ExportRangeAsCSV(ByVal rng As Range, delim As String, filepath As String)
Dim arr As Variant, line As String, csvContent As String, fso As Object, csvFile As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set csvFile = fso.OpenTextFile(filepath, 2, True)
arr = rng.Value 'Filter
If IsArray(arr) Then
' um die Überschrift im CSV oben einzufügen
Dim col As Range
For Each col In rng.Columns
If Len(line) > 0 Then line = line & delim
line = line & """" & rng.Parent.Cells(1, col.column) & """"
Next
csvContent = line & vbNewLine
'um die Werte ins CSV einzufügen
For r = 1 To UBound(arr, 1)
line = ""
For c = 1 To UBound(arr, 2)
If c < UBound(arr, 2) Then
line = line & """" & arr(r, c) & """" & delim
Else
line = line & """" & arr(r, c) & """"
End If
Next
csvContent = csvContent & line & vbNewLine
Next
csvFile.Write (csvContent)
csvFile.Close
Else
MsgBox "Bereich besteht nur aus einer Zelle!", vbExclamation
End If
Set fso = Nothing
Set csvFile = Nothing
End Sub
The Range("ov").value is the date and Range("ow").value the amount (double)
As you are already writing the CSV-File manually, I would suggest to introduce a function that converts your cell content as a string. You could use this routine for multiple purposes, eg format numbers (decimals, number of digits...), get rid of unwanted characters in as string (eg Newlines, semicolon, quote characers)...
Just to give you an idea:
Function FormatCellValue(v As Variant) As String
If IsDate(v) Then
FormatCellValue = Format(v, "dd.mm.yyyy hh:mm")
ElseIf VarType(v) = vbDecimal Then
FormatCellValue = Format(v, "#####.00")
ElseIf VarType(v) = vbString Then
v = Replace(v, vbCr, " ")
v = Replace(v, vbLf, " ")
v = Replace(v, ";", ",")
v = Replace(v, """", "'")
FormatCellValue = v
Else
FormatCellValue = v
End If
End Function
And in your existing code, simply write
line = line & """" & FormatCellValue(arr(r, c)) & """"
Update
If you want to write only strings with quote and dates (and numbers) without, you could add the quotes in the FormatCell-function: In the Vartype = vbString-branch, write
FormatCellValue = """" & v & """"
and change the call to
line = line & FormatCellValue(arr(r, c))
Excel really sucks at formatting numbers because the internal systems keep the stored value and displayed value separately. So what you see is not what will end up in the file when you save. To force excel to actually apply the formatting to the stored value, I use quotes to turn numbers & dates into strings. Like [A1].formula = "=""" & [A1].Value & """" which would turn a cell containing the number 100.00 into ="100.00" a literal string that excel can't reformat.
For your date format situation, you can do [A1].formula = "=""" & Format([A1].Value, "dd/mm/yyyy hh:nn") & """". Which will force excel to save the cell value in the specified format and ensure the output csv is in that format.
Here is a function that I have used previously to change a 2D array of values into an array of formulas as described above.
Private Function ForceString(ByRef InputArr As Variant) As Variant
Dim OutputArr() As Variant
OutputArr = InputArr
Dim i As Long, j As Long
For i = LBound(OutputArr) To UBound(OutputArr)
For j = LBound(OutputArr, 2) To UBound(OutputArr, 2)
If Len(OutputArr(i, j)) < 255 Then
OutputArr(i, j) = "=""" & OutputArr(i, j) & """"
Else
Dim k As Long, Tmp As String
Tmp = "="
For k = 1 To Len(OutputArr(i, j)) Step 255
Tmp = Tmp & IIf(k <> 1, "&", "") & """" & Mid(OutputArr(i, j), 1, 255) & """"
Next k
OutputArr(i, j) = Tmp
End If
Next j
Next i
ForceString = OutputArr
End Function
The If/Else in the middle is due to the limitation in excel about a literal string inside a formula not being allowed to have more than 255 characters. In those cases, it just has to be split up into multiple strings, but the output value is still the same.

Run time error 1004 when trying to input hyperlinks into cells

I seem to have no problem adding a hyperlink into one cell but when I try and add into multiple cells there is a problem. I have also tried using .formula method and writing out the =HYPERLINK formula but that encountered the same issue... any help would be greatly appreciated!
With Sheets(sheetName)
.Hyperlinks.Add Anchor:=.Range("B1"), _
Address:=folderName, _
TextToDisplay:="Client"
End With
For i = 0 To lastRow - 2
If reportRequired(i) = "Yes" Then
fileName = folderName + "\" + clients(i) + ".docx"
With Sheets(sheetName)
.Hyperlinks.Add Anchor:=.Range(Cells(i + 2, 2)), _
Address:=fileName, _
TextToDisplay:=clients(i)
End With
End If
Next i
Using the hyperlink formula I tried this way as well:
For i = 0 To lastRow - 2
If reportRequired(i) = "Yes" Then
fileName = folderName + "\" + clients(i) + ".docx"
Sheets(sheetName).Range(Cells(i + 2, 2)).formula = "=HYPERLINK(" + fileName + """ + clients(i) + """ + ")"
End If
Next i

Memory problem with macro in Excel: How do I solve this problem?

I have a problem with a macro in Excel. Here the code. There are actually quite a few subs that are I am not reporting for a matter of space. However, the most important one is attached.
Sub randomdata_generator()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim FromProducts As Integer
Dim ToProducts As Integer
Dim StepProducts As Integer
Dim FromStations As Integer
Dim ToStations As Integer
Dim StepStations As Integer
FromProducts = Range("G1").Value
ToProducts = Range("I1").Value
StepProducts = Range("K1").Value
FromStations = Range("G2").Value
ToStations = Range("I2").Value
StepStations = Range("K2").Value
For h1 = FromProducts To ToProducts Step StepProducts
For h2 = FromStations To ToStations Step StepStations
Index = 0
For xx1 = 1 To 17 Step 1 'NC
x1 = h1
x2 = h2
Range("B1").Value = x1
D = Application.WorksheetFunction.Round(x1 * 0.1, 0)
E = Application.WorksheetFunction.Round(x1 * 0.2, 0)
BAEG = Application.WorksheetFunction.Round(x1 * 0.35, 0)
For xx2 = 1 To 5 Step 1
If x2 >= x1 Then GoTo prossimo
Range("B2").Value = x2
Range("B4").Value = 20 * x2 'D
For x3 = 1 To 5 'NI
Range("B3").Value = x3
If x3 > 1 Then
q = 3
Else
q = 1
End If
For g = 1 To q
x5 = 1
Range("B5").Value = x5
s = E
For i = 0 To s - 1
Range("A25").Offset(0, D + i).Value = 0.3
Range("A28").Offset(0, D + i).Value = 0.2
Range("A46").Offset(0, D + i).Value = 0.009
Next
Next
Next
Next
Next
Next
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
This is the part of the code that saves the new file that has been generated.
Sub salvanuovo()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim wbkCurrent As Workbook
Index = Index + 1
If Index Mod 200 = 0 Then
newHour = Hour(Now())
newMinute = Minute(Now()) + 1
newSecond = Second(Now()) + 30
waitTime = TimeSerial(newHour, newMinute, newSecond)
Application.Wait waitTime
DoEvents
End If
ActiveWorkbook.SaveCopyAs Filename:=ThisWorkbook.Path & "\Data\Dati(" & (x1 / 10) & "_" & (x2) & "_" & Index & ").xlsm" 'example: "C:\Users\lucag\Desktop\randomdata_generator_alternativa\Dati(" & Index & ").xlsm"
Workbooks.Open Filename:=ThisWorkbook.Path & "\Data\Dati(" & (x1 / 10) & "_" & (x2) & "_" & Index & ").xlsm"
Workbooks("Dati(" & (x1 / 10) & "_" & (x2) & "_" & Index & ").xlsm").Activate
Sheets("Foglio1").Select
ActiveWorkbook.SaveAs Filename:=ThisWorkbook.Path & "\Data\Dati(" & (x1 / 10) & "_" & (x2) & "_" & Index & ").xlsx", _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
Workbooks("Dati(" & (x1 / 10) & "_" & (x2) & "_" & Index & ").xlsx").Close
Kill (ThisWorkbook.Path & "\Data\Dati(" & (x1 / 10) & "_" & (x2) & "_" & Index & ").xlsm")
Set wbkCurrent = ActiveWorkbook
wbkCurrent.Activate
Set wbkCurrent = Nothing
End Sub
The following image shows the issue. The memory keeps loading until Excel crashes. Any hint on how to solve this problem.
enter image description here
There is no .Copy nor .Paste just some .Value assigned
Selection.ClearContents
Range("A12").Select
This is not a comprehensive answer, just somewhat of a start.
First, Excel VBA treats Integer types as Long internally. This answer shows more on that. So I would recommend using Long unless specific to backward compatibility for older Excel versions.
Next I see you are using worksheet functions. You don't need
D = Application.WorksheetFunction.Round(x1 * 0.1, 0)
as it can be reduced to
D = Round(x1 * 0.1, 0)
On top of that, you are accessing the worksheet an insane amount of times through the nested loops. It would be better, in my opinion, to limit the amount of times VBA must interact with ranges or worksheets to the minimum number of times, such as storing values into an array and dump the full array to the cells.
Additionally, you can look at this answer regarding memory problems as there are quite a few tips that may be applicable here.
And as a total side note, I would recommend using more meaningful variable names, especially when presenting to SO to help people determine what is going on.
The problem was related to the version of Excel. As soon as I move to a 64-bit version of Office 365 rather than the 32-bit version that I had before, everything was solved.

VBA excel - excel creating empty csv files when using application.ontime

I got a macro that runs every 30 seconds using Application.Ontime. Every iteration creates a new csv file containing 8 columns and between 50 to 100 rows. The Application.Ontime normally runs from 8am to 5pm.
The problem is that sometimes during the day the macro just stop storing data in the csv files but still creates csv files. Hence, it still creates csv files but without any data in it.
EDIT:
The files that are created contain headers (StdTenorArray(0))
The variable StdXXXXXX is defined in another macro (button) and is a global variable
Here is the code:
Sub RunOnTime()
Application.CutCopyMode = False
Set ThisWkb = ThisWorkbook
dTime = Now + TimeSerial(0, 0, 30)
Application.OnTime dTime, "RunOnTime"
Call csvFileArray
Set ThisWkb = Nothing
End Sub
The above code calls this macro:
Sub csvFileArray()
Dim StdTenorArray(), ArkArr(5) As Variant
Dim FileName As String
Dim StdTenorCnt, h, j As Long
Set ThisWkb = ThisWorkbook
Application.CutCopyMode = False
ArkArr(1) = "XXXXXXctb"
ArkArr(2) = "XXXXXctb"
ArkArr(3) = "XXXXctb"
ArkArr(4) = "XXXctb"
ArkArr(5) = "XXctb"
ReDim StdTenorArray(ThisWkb.Sheets(ArkArr(1)).Range("B" & Rows.Count).End(xlUp).Row + ThisWkb.Sheets(ArkArr(2)).Range("B" & Rows.Count).End(xlUp).Row + ThisWkb.Sheets(ArkArr(3)).Range("B" & Rows.Count).End(xlUp).Row + ThisWkb.Sheets(ArkArr(4)).Range("B" & Rows.Count).End(xlUp).Row + ThisWkb.Sheets(ArkArr(5)).Range("B" & Rows.Count).End(xlUp).Row)
'Standard tenors
StdTenorCnt = 1
If StdXXXXXX = True Then
For j = 5 To 29
If UCase(ThisWkb.Sheets(ArkArr(1)).Cells(j, 4)) = True _
And WorksheetFunction.IsNumber(ThisWkb.Sheets(ArkArr(1)).Cells(j, 10)) = True _
And WorksheetFunction.IsNumber(ThisWkb.Sheets(ArkArr(1)).Cells(j, 11)) = True _
And IsDate(ThisWkb.Sheets(ArkArr(1)).Cells(j, 7)) = True _
And IsDate(ThisWkb.Sheets(ArkArr(1)).Cells(j, 8)) = True Then
StdTenorArray(StdTenorCnt) = "" & ThisWkb.Sheets(ArkArr(1)).Cells(j, 5) & ";" & Format(ThisWkb.Sheets(ArkArr(1)).Cells(j, 7), "yyyymmdd") & ";" & Format(ThisWkb.Sheets(ArkArr(1)).Cells(j, 8), "yyyymmdd") & ";" & ThisWkb.Sheets(ArkArr(1)).Cells(j, 9) & ";" & Replace(Format(ThisWkb.Sheets(ArkArr(1)).Cells(j, 10), "##0.00"), ",", ".") & ";" & Replace(Format(ThisWkb.Sheets(ArkArr(1)).Cells(j, 11), "##0.00"), ",", ".") & ";" & ThisWkb.Sheets(ArkArr(1)).Cells(j, 6) & ";JPD"
StdTenorCnt = StdTenorCnt + 1
End If
Next j
End I.
.
.
'more storing in the array like the part above
.
.
StdTenorArray(0) = "Symbol;SpotDate;ValueDate;Removed;Bid;Offer;Tenor;Channel"
Set fs = CreateObject("Scripting.FileSystemObject")
'test
app_path = ThisWkb.Path
Set a = fs.CreateTextFile("" & app_path & "\Test\" & Strings.Format(Now(), "dd.mm.yyyy") & " " & Strings.Format(Now(), "hh.mm.ss") & "." & Strings.Right(Strings.Format(Timer(), "#0.00"), 2) & ".csv", True)
For j = 0 To StdTenorCnt - 1
a.WriteLine ("" & StdTenorArray(j) & "")
Next j
a.Close
ThisWkb.Sheets("DKK").Cells(1, 27) = "" & Strings.Format(Now(), "hh:mm:ss") & ":" & Strings.Right(Strings.Format(Timer(), "#0.00"), 2) & ""
ReDim StdTenorArray(0)
Set fs = Nothing
Set a = Nothing
Set ThisWkb = Nothing
Application.CutCopyMode = False
End Sub
Hope someone have a solution to this problem or maybe can point me in the right direction.
Have a nice weekend.
\Kristian

SaveAs failing despite not changing the code

I have a function in a larger macro that helps reformat and clean up some data from a specific measurement file so that it can be used by the rest of the macro. I recently needed to update some of the data clean-up & reformatting that the function does based on guidance from the department that uses the macro. Those changes work fine, but now the .SaveAs is failing on Error 1004 "SaveAs method of object '_Workbook' failed".
I compared the old & new versions in a text comparison program (UltraCompare) and the changes definitely shouldn't impact the SaveAs. If I stop the macro at the point just before SaveAs and manually save that works successfully, so nothing in the file itself is blocking the save, nor is it a permissions change I didn't know about (which is extra not likely since the test folder is a child of my Desktop).
To go through some of the answers I've seen to other questions on this error
I don't use ActiveWorkbook to save, I create the workbook when setting a workbook variable
I don't use a date in the save as file name
There are no hyperlinks in the workbook
Excel doesn't throw a prompt, and alerts are left on prior to the SaveAs line
As mentioned above, the save is to a folder off my Desktop, so network drive mapping involved
Some additional things I've tried:
During debug, creating a new variable immediately prior to the .SaveAs line & populating it with a new file name in the same folder, and using that in the .SaveAs in place of the replace
Again with a new variable prior to .SaveAs that specifies a different folder
Specifying FileFormat:=51
All that said, here's the code, if anyone has ideas I'm game:
Function MergeCDC(sw As StatWin, fpath As String, BadDateRef As Range, Optional FromComb As Boolean = False) As Boolean
'StatWin is a custom form with a text box for printing status text to the user & a progress bar. fpath is the full file path of the file to be used as a string (folder path & file name including file extension)
'BadDateRef is a cell in the workbook that holds this function that holds the date 1/1/1900 which is used by the file being processed to indicate no date (i.e. the field should be null, but the DBAs
'decided to be weird so we have to deal with it)
'FromComb is a way to know if this function was called by a specific other function, so that run time tracking can be handled correctly
'Check if we're blocked on CDC (this prevents the function from trying to run again if it's called a second (or greater) time after failing)
If sw.CDCBlock Then
MergeCDC = False
Exit Function
End If 'else continue
Dim src As Workbook
Set src = Workbooks.Open(fpath) 'No need to check if the CDC workbook is present as that was done prior to this function being invoked
Dim ry As Worksheet
Dim ytd As Worksheet
Dim m As Workbook
Set m = Workbooks.Add
Dim ms As Worksheet
Set ms = m.Worksheets(1)
Dim ret As Boolean
ret = False
Dim c As Long
Dim r As Long
Dim ryc As Long
Dim temp() As Long
Dim msc As Long
Dim z As Integer
Dim yfnd As Boolean
Dim rfnd As Boolean
'Update the RunStat sheet such that we track CDC data merge as it's own item
If FromComb Then
sw.RStat.Range("A" & sw.StatRow + 2).Value = sw.RStat.Range("A" & sw.StatRow + 1).Value
sw.RStat.Range("B" & sw.StatRow + 2).Value = sw.RStat.Range("B" & sw.StatRow + 1).Value 'Bump start time for combined list being created
sw.RStat.Range("A" & sw.StatRow + 1).Value = sw.RStat.Range("A" & sw.StatRow).Value 'bump start for creation of combined source file
sw.RStat.Range("B" & sw.StatRow + 1).Value = sw.RStat.Range("B" & sw.StatRow).Value
Else
sw.RStat.Range("A" & sw.StatRow + 1).Value = sw.RStat.Range("A" & sw.StatRow).Value 'bump start for creation of CDC list
sw.RStat.Range("B" & sw.StatRow + 1).Value = sw.RStat.Range("B" & sw.StatRow).Value
End If
sw.RStat.Range("A" & sw.StatRow).Value = "CDC Merge"
sw.RStat.Range("B" & sw.StatRow).Value = Now()
'Determine which sheet is which
z = 1
yfnd = True
rfnd = True
Do While z <= src.Worksheets.Count And (yfnd Or rfnd)
If InStr(1, UCase(src.Worksheets(z).Name), "YTD") > 0 Then
yfnd = False
Set ytd = src.Worksheets(z)
ElseIf InStr(1, UCase(src.Worksheets(z).Name), "RY") > 0 Then
rfnd = False
Set ry = src.Worksheets(z)
End If
z = z + 1
Loop
'Check we found both sheets
If rfnd Or yfnd Then
Call Err("Unable to locate the RY and/or YTD worksheets in the Unedited CDC file. Please update the file such that the YTD worksheet includes 'YTD' in its name, and the RY" _
& " worksheet includes 'RY' in its name. This error prevents any list utilizing CDC data from being completed.", sw)
MergeCDC = False
sw.CDCBlock = True
Exit Function
End If 'else continue as normal
'Prep the two worksheets
temp = CDCPrep(ry, True, sw)
ryc = temp(0)
r = temp(1) 'CDCPrep returns the first BLANK row so we will use r as the row to paste to when pasting YTD data
'Prep of RY successful?
If temp(0) <> -1 Then
temp = CDCPrep(ytd, False, sw)
Else
'Close the new workbook without saving
m.Close SaveChanges:=False
End If
'Continue?
If temp(0) <> -1 Then
'Copy the entirety of Rolling Year data
ry.Range("A1:" & ColNumToStr(ryc) & r - 1).Copy
ms.Range("A1").PasteSpecial xlPasteAll
'Start merging in the YTD data. Since we can't assume the columns are in the same order we'll start iterating through the RY columns and copying one column at a time from YTD
c = 0
Do While ms.Range("A1").Offset(0, c).Value <> ""
'Find the matching column in YTD
msc = 0
Dim fnd As Boolean
fnd = False
Do While ytd.Range("A1").Offset(0, msc).Value <> "" And fnd = False
If ytd.Range("A1").Offset(0, msc).Value = ms.Range("A1").Offset(0, c).Value Then
'Found the column. Copy it's data
fnd = True
ytd.Range(ColNumToStr(msc + 1) & "2:" & ColNumToStr(msc + 1) & temp(1)).Copy
Else
msc = msc + 1
End If
Loop
'Did we find a match?
If fnd Then
'Paste the data
ms.Range("A" & r).Offset(0, c).PasteSpecial xlPasteAll
Else
Call Err("Unable to locate the " & ms.Range("A1").Offset(0, c).Value & " column in the Yr To Date data. The list will be generated, but will be missing these values for items found only" _
& " in the Yr To Date data.", sw)
End If
c = c + 1
Loop
'Get the last row of data so we can sort the merged data
r = r + temp(1)
'Check that is the last row
Do While ms.Range("A" & r).Value <> "" And r < 600000 'ridiculously high value, but serves as a fail-safe to keep from hitting end of sheet and not having found data end
r = r + 1
Loop
'Sort the data and remove duplicates according to the current month (Jan - Jun: RY rows preferred to YTD; Jul - Dec: YTD preferred)
If Month(sw.CurDate) < 7 Then
'RY preferred
ms.Sort.SortFields.Clear
ms.Sort.SortFields.Add Key:=Range _
("A2:A" & r), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
ms.Sort.SortFields.Add Key:=Range _
("B2:B" & r), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ms.Sort
.SetRange Range("A1:" & ColNumToStr(c + 1) & r + temp(1))
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Else
'YTD preferred
ms.Sort.SortFields.Clear
ms.Sort.SortFields.Add Key:=Range _
("A2:A" & r), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
ms.Sort.SortFields.Add Key:=Range _
("B2:B" & r), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:= _
xlSortNormal
With ms.Sort
.SetRange Range("A1:" & ColNumToStr(c + 1) & r + temp(1))
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End If
ms.Range("A1:" & ColNumToStr(c + 1) & r + temp(1)).RemoveDuplicates Columns:=1, Header:=xlYes
'Delete the MergeKey & Source columns
ms.Range("A:B").Delete Shift:=xlLeft
'In order to be processed correctly by other functions later certain target values (Last Test Date, Last Test Value) need to be inserted as new SubMeasures (i.e. new rows)
Dim i As Long
Dim ik As String
Dim sm As String
Dim nc As String
Dim ltd As String
Dim ltv As String
Dim td As String
i = 0
fnd = True
'To add the rows we need to be able to tell when we're on the first row of data for a particular item. Meaning we need to know the column holding ItemKey
Do While ms.Range("A1").Offset(0, i).Value <> "" And fnd
Select Case LCase(ms.Range("A1").Offset(0, i).Value)
Case "itemkey"
mk = ColNumToStr(i + 1)
Case "submeasure"
sm = ColNumToStr(i + 1)
Case "numercnt"
nc = ColNumToStr(i + 1)
Case "date1"
ltd = ColNumToStr(i + 1)
Case "last_val"
ltv = ColNumToStr(i + 1)
Case "terminationdate"
td = ColNumToStr(i + 1)
End Select
i = i + 1
If sm <> "" And ik <> "" And td <> "" And ltd <> "" And nc <> "" And ltv <> "" Then
fnd = False
End If
Loop
If fnd Then
'Couldn't find the needed columns. Report the error
Call Err("Unable to locate the one or more of the following columns in the MergedCDC file: ItemKey, SubMeasure, NumerCnt, TerminationDate, Last Test Date, Last Test Value. This will prevent adding" _
& " rows for Last Test Value & Last Test Date, which will in turn mean those columns will not be correctly populated in any list based on CDC data. All other values from" _
& " the CDC data should be correct though.", sw)
Else
'Add the rows
Dim PM As String
i = 2
Do While ms.Range(mk & i).Value <> ""
If InStr(1, PM, "|" & ms.Range(mk & i).Value & "|") = 0 Then
'First row for this item set all Term Date values are set to the MAX Term Date value for the item. Also determine if they're non-compliant on any measure
Dim y As Integer
Dim tdv As Date
Dim ncv As Integer
y = 0
tdv = DateSerial(1900, 1, 1)
ncv = 1 'Start # 1 so that if any row is non-compliant we can change ncv then (as opposed to having to make sure ALL rows are compliant before setting ncv to 1)
Do While ms.Range(mk & i + y).Value = ms.Range(mk & i).Value
If ms.Range(td & i + y).Value > tdv Then
tdv = ms.Range(td & i + y).Value
End If 'else the term date is older than tdv, and we want to standardize to the max term date, so leave tdv alone
If ms.Range(nc & i + y).Value < ncv Then
ncv = 0
ElseIf ms.Range(sm & i + y).Value = "Tested" Then
'Check if the Test Value = 0 and if the Last Test Date is valid
If (ms.Range(ltd & i + y).Value = DateSerial(1900, 1, 1) Or ms.Range(ltd & i + y).Value = "" Or ms.Range(ltd & i + y).Value = BadDateRef.Value) _
And ms.Range(lbg & i + y).Value = 0 Then
'The value is 0 and the date isn't valid, that means the item wasn't actually tested (in effect if not actuality). Set this row to not tested & update ncv
ms.Range(nc & i + y).Value = 0
ncv = 0
End If 'else the item was tested, the compliance value stays the same, which means ncv doesn't need changed
End If 'Else row indicates item is compliant, which is the default, so no action needed
y = y + 1
Loop
'Replace Term Date values that aren't TDV with TDV (technically, we also replace the row that set TDV, but with the same value)
If tdv <> DateSerial(1900, 1, 1) Then
y = 0
Do While ms.Range(mk & i + y).Value = ms.Range(mk & i).Value
ms.Range(td & i + y).Value = tdv
y = y + 1
Loop
Else
'No actual date found for TDV, just clear the cells setting the format to General so that Excel doesn't re-fill in 1/1/1900
y = 0
Do While ms.Range(mk & i + y).Value = ms.Range(mk & i).Value
ms.Range(td & i + y).NumberFormat = "General"
ms.Range(td & i + y).ClearContents
y = y + 1
Loop
End If
'Copy the current row & insert two copies of it below the current row
ms.Range(i & ":" & i).Copy
ms.Range(i + 1 & ":" & i + 1).Insert Shift:=xlDown
ms.Range(i & ":" & i).Copy
ms.Range(i + 1 & ":" & i + 1).Insert Shift:=xlDown
'Change the SubMeasure cells appropriately
ms.Range(sm & i + 1).Value = "Last Test Date"
ms.Range(sm & i + 2).Value = "Last Test Val"
'Set the compliance cnt value. If the item's last value is 0 AND there is no Last Test Date value, the numercnt value for the two added rows should be 0 so that date & value
' appear (as even though they're compliant, they probably shouldn't be marked as such due to lack of proof). If the value is non-0 then set based on ncv
If ms.Range(lbg & i).Value = 0 & ms.Range(ltd & i + y).Value = "" Then
ms.Range(nc & i + 1).Value = 0
ms.Range(nc & i + 2).Value = 0
Else
ms.Range(nc & i + 1).Value = ncv
ms.Range(nc & i + 2).Value = ncv
End If
'Add the item to PM, a delimited string of ItemKeys for processed items that lets us check if we've already seen a row for this item
PM = PM & "|" & ms.Range(mk & i).Value & "|"
'Add 2 to i (this way the additional incrementing of i below results in us looking at row i + 3, which was the row that had been immediately below row i before we added the two new rows)
i = i + 2
End If 'else proceed to the next row, which happens anyway
i = i + 1
Loop
End If
'Clear out compliant rows so that MergedCDC processes through MFPRocessor (a seperate function that we're setting up the CDC data to go through) like any other source file
'(submeasure present = item non-compliant on measure)
i = 2
Do While ms.Range(mk & i).Value <> ""
If ms.Range(nc & i).Value = 1 Then
ms.Range(i & ":" & i).Delete Shift:=xlUp
Else
i = i + 1
End If
Loop
'Remove 1/1/1900 values from Last Test Date & Term Date
i = 2
Do While ms.Range(mk & i).Value <> ""
If ms.Range(ltd & i).Value = "1/1/1900" Or ms.Range(ltd & i).Value = BadDateRef.Value Then
ms.Range(ltd & i).NumberFormat = "General"
ms.Range(ltd & i).ClearContents
End If
If ms.Range(td & i).Value = "1/1/1900" Or ms.Range(td & i).Value = BadDateRef.Value Then
ms.Range(td & i).NumberFormat = "General"
ms.Range(td & i).ClearContents
End If
i = i + 1
Loop
ret = True
'Save the workbook
m.SaveAs (Replace(fpath, "CDC", "MergedCDC")) 'This code HAD worked, despite none of the changes being anything that should impact this line, this line
Application.DisplayAlerts = False
m.Close SaveChanges:=False
Application.DisplayAlerts = True
Else
'Close the new workbook without saving
m.Close SaveChanges:=False
End If
'Close the original CDC workbook
Application.DisplayAlerts = False
src.Close
Application.DisplayAlerts = True
'Capture completion of CDC merge
sw.RStat.Range("C" & sw.StatRow).Value = Now()
sw.StatRow = sw.StatRow + 1
MergeCDC = ret
End Function
If you haven't changed your code then here's a few things to check which could be causing the error:
Workbook object is out of context - ensure that you are using only one instance of Excel, if your data and workbook are in different instances then they wont be able to reach each other. When your code breaks at the error, add the workbook to your watch list to see if it reachable.
Filepath is unreachable - when the code breaks at this error, take the value of Replace(fpath, "CDC", "MergedCDC") without the filename at the end, and paste it into windows explorer and check that it is reachable.

Resources