VBScript Opening CSV and splitting - excel

I have made a script that allows the user to open a file using the shell browser and once selected they are prompted to enter the interval in which they want to split the .CSV file down into smaller files.
The problem that arises is that once I select the file using the browser I get an unspecified error with the code 80004005 it appears on line 15 character 1 and I have no idea how to solve this.
Any help would be much appreciated!
Option Explicit
Const ForReading = 1
Const ForWriting = 2
Dim objFSO, objInputFile, objOutputFile
Dim intLine, intFile
Dim strHeaders
Dim strInputFile, strOutputPrefix, strLine
Dim MyDate
Dim shell
Dim file
Set shell = CreateObject("Shell.Application")
Set file = shell.BrowseForFolder(0, "Choose a file:", &H4000)
BrowseForFile = file.self.Path
strInputFile = BrowseForFile
strOutputPrefix = objFSO.GetBaseName(strInputFile) & DatePart("yyyy", Now) & "-" & DatePart("m", Now) & "-" & DatePart("d", Now)
userSplit = InputBox("Enter when you want to split")
intFile = 1
intLine = 0
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInputFile = objFSO.OpenTextFile(strInputFile, ForReading)
If (objInputFile.AtEndOfStream = True) Then
' The file is empty
WScript.Quit 1
End If
strHeaders = objInputFile.ReadLine
Do While (objInputFile.AtEndOfStream = False)
strLine = objInputFile.ReadLine
If (intLine <= 0) Then
Set objOutputFile = objFSO.CreateTextFile(strOutputPrefix & "_" & intFile & ".csv", True)
objOutputFile.WriteLine strHeaders
intLine = 1
End If
objOutputFile.WriteLine strLine
If (intLine >= userSplit) Then
objOutputFile.Close
Set objOutputFile = Nothing
intFile = intFile + 1
intLine = 0
Else
intLine = intLine + 1
End If
Loop

Your BrowseForFolder call misses the third/option parameter; so change
Set file = shell.BrowseForFolder(0, "Choose a file:", &H4000)
to
Set file = shell.BrowseForFolder(0, "Choose a file:", 0, &H4000)
The above (kept for context for comments) is all wrong
The docs state clearly:
Creates a dialog box that enables the user to select a folder and then
returns the selected folder's Folder object.
so you can display the files, but not pick/return them.

Related

Exporting listbox values from mc access form to excel file maintaining the same number of columns

So I managed to create a code to copy and paste listbox values to a newly created excel file.
The thing is, I have it all concatenated and separated by a comma. It works fine but because of how it is exported, then I have to use Excel text to columns functionality to put the data like I want.
Here's the code:
Private Sub button_Export_AMAT_Click()
Dim i As Integer
Dim n As Integer
Dim strLine As String
Set fs = CreateObject("Scripting.FileSystemObject")
Set a = fs.CreateTextFile("\\yvavm301\Commun\CF_GDC\base de dados a trabalhar\AM_AT.csv", True)
For i = 0 To Me.List_AM_AT.ListCount - 1
For n = 0 To Me.List_AM_AT.ColumnCount - 1
strLine = strLine & """" & Me.List_AM_AT.Column(n, i) & ""","
Next n
strLine = Left(strLine, Len(strLine) - 1)
a.writeline (strLine)
strLine = ""
Next i
MsgBox "Your file is exported"
End Sub
My question is: is it possible to export a like for like table, ie. having the same number of columns and having them populated with right values?
The change has to be made here (see below), right?
strLine = strLine & """" & Me.List_AM_AT.Column(n, i) & ""","
a.writeline (strLine)
I've tried without luck the following:
strLine = Me.List_AM_AT.Column(n, i)
a.cells(i,n).writeline (strLine)
Does anyone have an idea of what to do?
As said in my comment you could create an Excel file in your code and write the values to that file. Right now you create a text file with your code which leads to the issues you describe in your post (text assistant etc.)
Private Sub button_Export_AMAT_Click()
Dim i As Integer
Dim n As Integer
' You might need to add a reference to Excel if your host application is Access
' Extra/Reference and select Microsoft Excel Object Library
Dim xl As Excel.Application
Set xl = New Excel.Application
Dim wkb As Workbook
Set wkb = xl.Workbooks.Add
Dim wks As Worksheet
Set wks = wkb.Sheets(1)
'Dim strLine As String
'Set fs = CreateObject("Scripting.FileSystemObject")
'Set a = fs.CreateTextFile("\\yvavm301\Commun\CF_GDC\base de dados a trabalhar\AM_AT.csv", True)
For i = 0 To Me.List_AM_AT.ListCount - 1
For n = 0 To Me.List_AM_AT.ColumnCount - 1
wks.Cells(i + 1, n + 1).Value = Me.List_AM_AT.Column(n, i)
'strLine = strLine & """" & Me.List_AM_AT.Column(n, i) & ""","
Next n
'
' strLine = Left(strLine, Len(strLine) - 1)
' a.writeline (strLine)
' strLine = ""
Next i
wkb.SaveAs "D:\TMP\EXPORT.XLSX" ' Adjust accordingly
wkb.Close False
xl.Quit
MsgBox "Your file is exported"
End Sub

Changing password for multiple excel files in a folder

I have multiple files in a folder and each of them have different password (which I have with me). Every week, I need to open the file using the password and save it without password (for an automation to pick the files).
I am using the below code which does the job. But it's slow and takes a few mins even if it's less than 10 files. Anything wrong with the code?
Please help!
Sub blah()
Set objFSO = CreateObject("Scripting.FileSystemObject")
mFolder = "folder path"
Set mainfolder = objFSO.GetFolder(mFolder)
Dim xValue As String
Dim OutValue As String
Dim PW As String
For Each fil In mainfolder.Files
PW = ""
xValue = ""
OutValue = ""
xValue = fil.Name
For xIndex = 1 To VBA.Len(xValue)
If Not VBA.IsNumeric(VBA.Mid(xValue, xIndex, 1)) Then
OutValue = OutValue & VBA.Mid(xValue, xIndex, 1)
End If
Next
TextOnly = Split(OutValue, ".")
If LCase(Left(TextOnly(UBound(TextOnly)), 4)) = "xlsx" Then
PW = Replace(OutValue, ".xlsx", "taxipw")
ElseIf LCase(Left(TextOnly(UBound(TextOnly)), 3)) = "xls" Then
PW = Replace(OutValue, ".xls", "taxipw")
End If
Set myWB = Workbooks.Open(Filename:=fil, Password:=PW)
myWB.Password = ""
myWB.Close True
Next fil
End Sub

VBA: How to deal with an empty array from reading an XML file

I'm reading an XML file in VBA and then using that to extract some information to create another Output XML file. I only need to generate amn output file when the fields in the initial XML file are filled in.
Currently when it gets to an empty tag it fails. I've tried some of the empty array solutions I've found on here but they don't seem to work. Is my code that bad??
Private Sub gDialer()
For i = 7 To 30000
If Sheets("Latest Report").Cells(i, "AL").Value = "Active - G to sign" Then
If Sheets("Latest Report").Cells(i, "AJ").Value <> "" Then
GenerateReadXML "Z:\AReports\A\Reports\readXML\gRead" & i & ".xml", Sheets("Latest Report").Cells(i, "AJ").Value
sendXML "readXML\gRead" & i & ".xml", "gRead" & i & "response", "Read"
Set oXMLFile = CreateObject("Microsoft.XMLDOM")
XMLFileName = "Z:\AReports\A\Reports\fActivities\results\gRead" & i & "response.xml"
'MsgBox XMLFileName
oXMLFile.Load (XMLFileName)
Set Numnode = oXMLFile.SelectNodes("/result/data29/text()")
Set titleNode = oXMLFile.SelectNodes("/result/data25/text()")
Set firstNode = oXMLFile.SelectNodes("/result/data26/text()")
Set lastNode = oXMLFile.SelectNodes("/result/data27/text()")
On Error GoTo didntfindit
Dim numStr As String
Dim titleStr As String
Dim firstStr As String
Dim lastStr As String
'### here's where it fails ###
numStr = Numnode(0).NodeValue
titleStr = titleNode(0).NodeValue
firstStr = firstNode(0).NodeValue
lastStr = lastNode(0).NodeValue
GenerateDialerXML "Z:\AReports\A\Reports\dialerXML\dialer" & i & ".xml", Numnode(0).NodeValue, titleNode(0).NodeValue, firstNode(0).NodeValue, lastNode(0).NodeValue, Sheets("Latest Report").Cells(i, "AJ").Value, 87
sendDialerXML "dialer" & i & ".xml", sendHandshake, "gDResponse"
didntfindit:
End If
End If
Next i
End Sub
When it fails, it's because the XML is like this:
<data24>something</data24>
</data25>
</data26>
</data27>
<data28>something else</data28>
</data29>
It works fine when there are values, but I can't figure out the next step.
Thanks in advance!
I've fixed it now, here's what I came up with, hope this helps someone one day:
oXMLFile.Load (XMLFileName)
Set numNode = oXMLFile.getElementsByTagName("data29")
Set titleNode = oXMLFile.getElementsByTagName("data25")
Set firstNode = oXMLFile.getElementsByTagName("data26")
Set lastNode = oXMLFile.getElementsByTagName("data27")
On Error GoTo didntfindit
Dim numStr As String
Dim titleStr As String
Dim firstStr As String
Dim lastStr As String
numStr = numNode(0).Text
titleStr = titleNode(0).Text
firstStr = firstNode(0).Text
lastStr = lastNode(0).Text

Need help dealing with subfolders [duplicate]

This question already has answers here:
Recursively access subfolder files inside a folder
(2 answers)
Closed 6 years ago.
So I want to make a .vbs that edits all .txt in a folder. This the code I used, and the folder is C:\test folder.
Const ForReading = 1
Const ForWriting = 2
newline = ""
line = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "C:\test folder\"
Dim lineCount : lineCount = 0
Dim firstContent : firstContent = ""
Set objFolder = objFSO.GetFolder(objStartFolder)
Set colFiles = objFolder.Files
For Each objFile in colFiles
If LCase(objFSO.GetExtensionName(objFile)) = "txt" Then
lineCount = 0
firstContent = ""
FileName = objStartFolder & objFile.Name
Set objStream = objFSO.OpenTextFile(FileName, ForReading)
Do Until objStream.AtEndOfStream
lineCount = lineCount + 1
firstContent = firstContent & objStream.ReadLine & vbCrLf
If lineCount = line Then
firstContent = firstContent & newline & vbCrLf
End If
Loop
Set objStream = objFSO.OpenTextFile(FileName, ForWriting)
objStream.WriteLine firstContent
objStream.Close
End If
Next
It works. and changes all the text files to what I want them to say, but when I made a folder in C:\test folder called SF (C:\test folder\SF), all of the text files in SF don't change. How do I get it to work with subfolders?
Recursion is a function calling itself. It is used to walk trees.
ProcessFolder DirName
Sub ProcessFolder(FolderPath)
' On Error Resume Next
Set fldr = fso.GetFolder(FolderPath)
Set Fls = fldr.files
For Each thing in Fls
msgbox Thing.Name & " " & Thing.path
Next
Set fldrs = fldr.subfolders
For Each thing in fldrs
ProcessFolder thing.path
Next
End Sub

VBScript User input variable

I am creating a script to split csv files up, I want to let the user input the interval in which the files are split into new ones.
The problem I am having is that when I input the interval it isn't splitting, but yet if I hard code the value in it does split.
Option Explicit
Const ForReading = 1
Const ForWriting = 2
Dim objFSO, objInputFile, objOutputFile
Dim intLine, intFile
Dim strHeaders
Dim strInputFile, strOutputPrefix, strLine
Dim MyDate
Dim userSplit
Dim split
'strInputFile = InputBox("Enter file location")
strInputFile = "H:\VBS\domS_CUST.csv"
strOutputPrefix = strInputFile & DatePart("yyyy", Now) & "-" & DatePart("m", Now) & "-" & DatePart("d", Now)
intFile = 1
intLine = 0
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInputFile = objFSO.OpenTextFile(strInputFile, ForReading)
If (objInputFile.AtEndOfStream = True) Then
' The file is empty
WScript.Quit 1
End If
strHeaders = objInputFile.ReadLine
userSplit = InputBox("Enter when you want to split")
Do While (objInputFile.AtEndOfStream = False)
split = userSplit
strLine = objInputFile.ReadLine
If (intLine <= 0) Then
Set objOutputFile = objFSO.CreateTextFile(strOutputPrefix & "_" & intFile & ".csv", True)
objOutputFile.WriteLine strHeaders
intLine = 1
End If
objOutputFile.WriteLine strLine
If (intLine >= split) Then
objOutputFile.Close
Set objOutputFile = Nothing
intFile = intFile + 1
intLine = 0
Else
intLine = intLine + 1
End If
Loop
The input is this line:
userSplit = InputBox("Enter when you want to split")
And I cannot seem to get it to split at the value of this, any help would be much appreciated!
You have an On Error Resume Next in your code that you didn't show, otherwise the line
split = userSplit
would've raised the error
Illegal Assignment: 'split'
split is the name of a built-in function, so it cannot be used as a variable name. It's also completely unnecessary, because you could simply use userSplit without assigning its value to another variable.
Correction: As Ekkehard.Horner pointed out in the comments, the Dim split supersedes the built-in function definition, thus no error is raised.
However, the main reason why your code doesn't work as you expect is that the InputBox function returns a string value. To make the comparison with intLine work correctly, you need to convert the string to an integer or long integer:
userSplit = CLng(InputBox("Enter when you want to split"))
...
If (intLine >= userSplit) Then
And you should at least add a check to handle situations where the user pressed "Cancel":
userSplit = CLng(InputBox("Enter when you want to split"))
If userSplit <= 0 Then WScript.Quit 1
Also, by using the the Line property, your code could be simplified to this:
filename = "H:\VBS\domS_CUST.csv"
Set fso = CreateObject("Scripting.FileSystemObject")
Set infile = fso.OpenTextFile(filename)
prefix = fso.BuildPath(fso.GetParentFolderName(filename) _
, fso.GetBaseName(filename) & "_" & Year(Now) & "-" _
& Right("0" & Month(Now), 2) & "-" & Right("0" & Day(Now), 2) & "_")
userSplit = CLng(InputBox("Enter when you want to split"))
If userSplit <= 0 Then WScript.Quit 1
Do Until infile.AtEndOfStream
If infile.Line = 1 Then
headers = infile.ReadLine
Else
If (infile.Line - 2) Mod userSplit = 0 Then
If infile.Line > 2 Then outfile.Close
Set outfile = fso.CreateTextFile _
(prefix & (infile.Line - 2) \ userSplit + 1 & ".csv", True)
outfile.WriteLine headers
End If
outfile.WriteLine infile.ReadLine
End If
Loop
outfile.Close

Resources