Excel VBA - MkDir returns "Path not Found" when using variable - vba

So here's the relevant snippet of my code (COPSFolder is a constant defined elsewhere):
Sub CreateReport(ByRef InfoArray() As String)
Dim BlankReport As Workbook
Dim ReportSheet As Worksheet
Dim ProjFolder As String
ProjFolder = COPSFolder & "InProgress\" & InfoArray(3)
If Not Dir(ProjFolder, vbDirectory) = vbNullString Then
Debug.Print ProjFolder
MkDir ProjFolder <-----ERROR 76 HAPPENS HERE
End If
On the line indicated, ProjFolder & "InProgress\" is an existing directory. I'm trying to create a folder within it based on a value in an array of strings.
Here's what boggles me. If I replace "InfoArray(3)" with a string (ex. "12345") it works fine, but trying to use an element in the array will throw the error. The array is defined as a string everywhere it is referenced, and there are no type mismatches elsewhere in the Module.
edit: Public Const COPSFolder As String = "\\ktch163\COPS\"
edit2: here's another weird thing - if I replace InfoArray(3) with Str(InfoArray(3)) it seems towork. What I don't get is that the value of InfoArray(3) is already defined as a string. Also, it adds a space in front of the value. I can use Right(Str(InfoArray(3)), 5) I guess, but would like to figure out what the real issue is here.
edit3: as requested, here's how InfoArray() is populated:
Public Function GetPartInfo(ByRef TextFilePath As String) As String()
'Opens text file, returns array with each element being one line in the text file
'(Text file contents delimited by line break character)
Dim fso As FileSystemObject: Set fso = New FileSystemObject
Dim Info As Variant
Dim txtstream As Object
Dim item as Variant
Debug.Print TextFilePath
Set txtstream = fso.OpenTextFile(TextFilePath, ForReading, False)
GetPartInfo = Split(txtstream.ReadAll, Chr(10))
For Each item In GetPartInfo
item = Trim(item)
Next
End Function
Later on in the code - InfoArray = GetPartInfo(File.Path). (File.Path works fine, no errors when running GetPartInfo

The problem is that you are splitting using Chr(10) This is not removing the spaces. And hence when you are calling ProjFolder = COPSFolder & "InProgress\" & InfoArray(3), you have spaces in InfoArray(3)
You have 3 options
When you are creating the array, remove the spaces there OR
When you are assigning InfoArray = GetPartInfo(File.Path), remove the spaces there OR
Change the line ProjFolder = COPSFolder & "InProgress\" & InfoArray(3) to ProjFolder = COPSFolder & "InProgress\" & Trim(InfoArray(3))

Related

VBA VAL forcing a comma (,) instead of a period (.)

Basically, I am writting a small AutoCAD VBA that reads CSV files to run commands.
First, I put the csv into a string array (as it contains characters as well). One array position I need to use as a double for the command (as it requires it).
I though this would be a simple VAL() since it is supposed to keep the period regardlesss of my region.
Any insight is greatly appreciated.
Private Sub CommandButton2_Click()
sfilename = "C:\Users\Patrick.Legault\OneDrive - Cima+\Projects\AutoCAD Styles\" & ComboBox1.Value & ".csv"
Dim sLineFromFile As String
Dim name As String
Dim font As String
Dim height As String
Dim vlineItems() As String
Open sfilename For Input As #1
Do Until EOF(1)
Line Input #1, sLineFromFile
vlineItems = Split(sLineFromFile, ",")
Call add_textstyle(vlineItems)
Loop
Close #1
End Sub
Sub add_textstyle(vlineItems() As String)
'''Patrick Legault 2021-11-15
'''This routine creates new textstyles with height
Dim textStyle As AcadTextStyle
Dim TextColl As AcadTextStyles
Dim newfontstyle As String
Dim fontpath As String
Dim h_long As Double
fontpath = "C:\Users\Patrick.Legault\OneDrive - Cima+\Projects\AutoCAD Styles\Fonts" '''to be changed
Set TextColl = ThisDrawing.TextStyles '''get the textstyles from this drawing
Set textStyle = TextColl.add(vlineItems(1)) '''add new textstyle
textStyle.fontFile = fontpath & "\" & (vlineItems(2)) '''add new font style to textstyle
h_long = CDbl(Val(vlineItems(3))) ''this returns the value with comma
textStyle.height = (h_long)
MsgBox h_long
End Sub
The csv in question is below:
Text,STD,Romans.shx,2.032,Main Text heght and style
Text,MD,Romans.shx,3.048,
Text,LG,Romans.shx,4.064,
Text,BOM TEXT,Romans.shx,1.5875,Text for Bill of Material
Text,BOLD,Bold.shx,5.08,"Custom FortisBC ""SHX file (Bold)"
Text,BOLDFILL,Boldfill.shx,5.08,"Custom FortisBC ""SHX"" file (Boldfill)"
Text,DIM,Romans.shx,0,"Dim used in Dimension Style ""Engineering"""
Text,NAMEPLATE,Romans.shx,6.35,"Use ""bigfont.shx"""

VBA using ahtCommonOpenFileSave with ahtOFN_ALLOWMULTISELECT, error when selecting single file

Maybe I'm overlooking the obvious, but I cant figure out how to deal with a single result in an array.
I'm using Ken Getz ahtCommonFileOpenSave API in VBA to enable selecting multiple files, using the following code.
Private Sub btn_openfiles_Click()
Dim strFilter As String
Dim strInputFileName As String
Dim strFiles() As String
Dim a As Long
strFilter = ahtAddFilterItem(strFilter, "Images (*.PNG)", "*.PNG")
strFiles = ahtCommonFileOpenSave( _
Filter:=strFilter, _
OpenFile:=True, _
InitialDir:="T:\DTP\Programs\Default\", _
DialogTitle:="Please select an input file...", _
Flags:=ahtOFN_EXPLORER + ahtOFN_ALLOWMULTISELECT)
If IsArray(strFiles) Then
For a = 0 To UBound(strFiles)
Me.test_filenames = Me.test_filenames & strFiles(a) & vbCrLf
Next a
Else
Me.test_filenames = strFiles
End If
End Sub
I know that the result is an array, because I'm setting the ahtOFN_ALLOWMULTISELECT flag. When multiple files are selected, this goes well. But if only one file is selected, an
error 13 is thrown (type mismatch on strFiles)
because the return value of ahtCommonFileOpenSave is not an array.
I may be able to force an Array type just by adding a dummy value to the array produced by ahtCommonFileOpenSave and disregard this when processing the file names in the form, but maybe there is a better solution. Anyone have a suggestion?
As I already mentioned, overlooking the obvious. Changing the variable type into variant did the trick . ahtComminFileOpenSave returns the complete array when multiple files are selected and is always a Variant type. Luuk's suggestion works too (a variant type is used by default when the variable type is omitted).
The corrected (and amended) code is like this and works like a charm!
Private Sub btn_openfiles_Click()
Dim strFilter As String
Dim strInputFileName As String
Dim varFiles As Variant
Dim a As Long
strFilter = ahtAddFilterItem(strFilter, "Images (*.PNG)", "*.PNG")
Me.test_filenames = ""
varFiles = ahtCommonFileOpenSave( _
Filter:=strFilter, _
OpenFile:=True, _
InitialDir:="T:\DTP\Programs\Default\", _
DialogTitle:="Please select an input file...", _
Flags:=ahtOFN_EXPLORER + ahtOFN_ALLOWMULTISELECT)
If IsArray(varFiles) Then
For a = 0 To UBound(varFiles)
Me.test_filenames = Me.test_filenames & varFiles(a) & vbCrLf
Next a
Else
Me.test_filenames = varFiles
End If
End Sub

How can I format value between 2nd and 4th underscore in the file name?

I have VBA code to capture filenames to a table in an MS Access Database.
The values look like this:
FileName
----------------------------------------------------
WC1603992365_Michael_Cert_03-19-2019_858680723.csv
WC1603992365_John_Non-Cert_03-19-2019_858680722.csv
WC1703611403_Paul_Cert_03-27-2019_858679288.csv
Each filename has 4 _ underscores and the length of the filename varies.
I want to capture the value between the 2nd and the 3rd underscore, e.g.:
Cert
Non-Cert
Cert
I have another file downloading program, and it has "renaming" feature with a regular expression. And I set up the following:
Source file Name: (.*)\_(.*)\_(.*)\_(.*)\_\-(.*)\.(.*)
New File Name: \5.\6
In this example, I move the 5th section of the file name to the front, and add the file extension.
For example, WC1603992365_Michael_Cert_03-19-2019_858680723.csv would be saved as 858680723.csv in the folder.
Is there a way that I can use RegEx to capture 3rd section of the file name, and save the value in a field?
I tried VBA code, and searched SQL examples, but I did not find any.
Because the file name length is not fixed, I cannot use LEFT or RIGHT...
Thank you in advance.
One possible solution is to use the VBA Split function to split the string into an array of strings using the underscore as a delimiter, and then return the item at index 2 in this array.
For example, you could define a VBA function such as the following, residing in a public module:
Function StringElement(strStr, intIdx As Integer) As String
Dim strArr() As String
strArr = Split(Nz(strStr, ""), "_")
If intIdx <= UBound(strArr) Then StringElement = strArr(intIdx)
End Function
Here, I've defined the argument strStr as a Variant so that you may pass it Null values without error.
If supplied with a Null value or if the supplied index exceeds the bounds of the array returned by splitting the string using an underscore, the function will return an empty string.
You can then call the above function from a SQL statement:
select StringElement(t.Filename, 2) from Filenames t
Here I have assumed that your table is called Filenames - change this to suit.
This is the working code that I completed. Thank you for sharing your answers.
Public Function getSourceFiles()
Dim rs As Recordset
Dim strFile As String
Dim strPath As String
Dim newFileName As String
Dim FirstFileName As String
Dim newPathFileName As String
Dim RecSeq1 As Integer
Dim RecSeq2 As Integer
Dim FileName2 As String
Dim WrdArrat() As String
RecSeq1 = 0
Set rs = CurrentDb.OpenRecordset("tcsvFileNames", dbOpenDynaset) 'open a recordset
strPath = "c:\in\RegEx\"
strFile = Dir(strPath, vbNormal)
Do 'Loop through the balance of files
RecSeq1 = RecSeq1 + 1
If strFile = "" Then 'If no file, exit function
GoTo ExitHere
End If
FirstFileName = strPath & strFile
newFileName = strFile
newPathFileName = strPath & newFileName
FileName2 = strFile
Dim SubStrings() As String
SubStrings = Split(FileName2, "_")
Debug.Print SubStrings(2)
rs.AddNew
rs!FileName = strFile
rs!FileName68 = newFileName 'assign new files name max 68 characters
rs!Decision = SubStrings(2) 'extract the value after the 3rd underscore, and add it to Decision Field
rs.Update
Name FirstFileName As newPathFileName
strFile = Dir()
Loop
ExitHere:
Set rs = Nothing
MsgBox ("Directory list is complete.")
End Function

VBA Split data by new line word

I am trying to split data using VBA within word.
I have got the data using the following method
d = ActiveDocument.Tables(1).Cell(1, 1).Range.Text
This works and gets the correct data. Data for this example is
This
is
a
test
However, when I need to split the string into a list of strings using the delimiter as \n
Here is an example of the desired output
This,is,a,test
I am currently using
Dim dataTesting() As String
dataTesting() = Split(d, vbLf)
Debug.Print dataTesting(0)
However, this returns all the data and not just the first line.
Here is what I have tried within the Split function
\n
\n\r
\r
vbNewLine
vbLf
vbCr
vbCrLf
Word uses vbCr (ANSI 13) to write a "new" paragraph (created when you press ENTER) - represented in the Word UI by ¶ if the display of non-printing characters is activated.
In this case, the table cell content you show would look like this
This¶
is¶
a¶
test¶
The correct way to split an array delimited by a pilcro in Word is:
Dim d as String
d = ActiveDocument.Tables(1).Cell(1, 1).Range.Text
Dim dataTesting() As String
dataTesting() = Split(d, vbCr)
Debug.Print dataTesting(0) 'result is "This"
You can try this (regex splitter from this thread)
Sub fff()
Dim d As String
Dim dataTesting() As String
d = ActiveDocument.Tables(1).Cell(1, 1).Range.Text
dataTesting() = SplitRe(d, "\s+")
Debug.Print "1:" & dataTesting(0)
Debug.Print "2:" & dataTesting(1)
Debug.Print "3:" & dataTesting(2)
Debug.Print "4:" & dataTesting(3)
End Sub
Public Function SplitRe(Text As String, Pattern As String, Optional IgnoreCase As Boolean) As String()
Static re As Object
If re Is Nothing Then
Set re = CreateObject("VBScript.RegExp")
re.Global = True
re.MultiLine = True
End If
re.IgnoreCase = IgnoreCase
re.Pattern = Pattern
SplitRe = Strings.Split(re.Replace(Text, ChrW(-1)), ChrW(-1))
End Function
If this doesn't work, there may be strange unicode/Wprd characters in your Word doc. It may be soft breaks, for instance. You could try to not split with "\W+" in stead of "\s+". I cannot test this without your document.
Dim dataTesting() As String
dataTesting() = Split(d, vbLf)
Debug.Print dataTesting(0)
works fine and thank you very much for your example,
for why it have returned a whole array is because you have used 0 as index, in many programming languages 0 is the whole array, so the first element is ,
so in my case counting from 1 this perfectly split a string that I had troubles with.
To be more exact this is how it was used in my case
Dim dataTesting() As String
dataTesting() = Split(Document.LatheMachineSetup.Heads.Item(1).Comment, vbCrLf)
MsgBox (dataTesting(1))
And that comment is a multiline string.
Image
So this msg box returned exactly first line.

Using Split function to find last folder in file path with only one line

I have a function that looks like
Dim arrFold() As String
Dim lastFold As String
arrFold = Split(filePath, "\")
lastFold = arrFold(ubound(arrFold))
I am looking for a way to simplify this into just finding the last element on the first line, rather than having to define an array initially, what can be done to avoid adding that to memory?
debug.print mid(filePath, instrrev(filePath, chr(92))+1)
debug.print trim(right(replace(filePath, chr(92), space(999)), 999))
Sub findLast()
Dim myString As String
myString = "\File\lesser\evenless\least"
MsgBox InStrRev(myString, "\")
End Sub