Merge many CSV files - vba

I have set of 500 csv files. Each file has four columns and variable number of rows.
I want to merge all of these csv's into one common sheet. If someone can help me in doing this in PowerShell, it would be great.
Sample Data in Excel 1:
Name Age Marks Class
A 15 100 5
B 20 88 6
Sample Data in Excel 2:
Name Age Marks Class
C 11 99 2
Output :
Name Age Marks Class
A 15 100 5
B 20 88 6
C 11 99 2

If all the CSV files are in one folder then:
$res = #()
ls *.csv | %{
$temp = Import-CSV $_
$res += $temp
}
$res | Export-CSV .\ALLINFO.csv -NoTypeInformation
The break down:
$res = #() - Make an array called $res that will hold all the data. This isn't strictly required. You could do it in a way that appends to a result file directly.
ls *.csv | - Find all the CSV files in the folder and pass them to the next command.
%{$temp = Import-CSV $_; $res += $temp} - Take each of those files, import the CSV data into a holder variable called $temp. Add the contents of $temp to the collector variable $res. Again it is not necessary to use the intermediate $tamp variable, I just find it more clear to do so.
$res | Export-CSV .\ALLINFO.csv -NoTypeInformation - Now that the data from all the files is in $res, export $res to a new file.

If the files are large then you could merge them as text documents. This is a lot faster than importing csv-objects, but it requires that the properties and the order in which they're placed are equal in all files. Example:
$files = Get-ChildItem "*.csv"
#Get header
$text = #(Get-Content -Path $files[0].FullName -TotalCount 1)
$files | ForEach-Object {
#Get text but skip header
$text += Get-Content -Path $_.FullName | Select-Object -Skip 1
}
#Save merged csv
$text | Set-Content Output.csv
Output.csv
Name;Age;Marks;Class
A;15;100;5
B;20;88;6
C;11;99;2
You could optimize it even more by replacing Get-Content for [System.IO.File]::ReadAllLines() etc. but I skipped that now as it's more complicated/hard to read.
UPDATE: Added alternative solution that saves the output-file part for part as Ansgar suggested.
$outputfile = "Output.csv"
$files = Get-ChildItem "*.csv"
#Get header
Get-Content -Path $files[0].FullName -TotalCount 1 | Set-Content -Path $outputfile
$files | ForEach-Object {
#Get text but skip header
Get-Content -Path $_.FullName | Select-Object -Skip 1
} | Add-Content -Path $outputfile

In your case, the sort name is optional depending on whether the merge should also reorder the contents (obviously, you can sort on a different parameter as well). Same stipulation as above - all .csv files in one directory.
dir c:\directory_containing_your\*.csv | Import-Csv | sort name | Export-Csv -Path c:\output.csv -NoTypeInformation
From the ScriptingGuy.

Here's a heavily-commented solution that uses VBA in Excel to combine the CSVs. The strategy here is this:
Set your references up-front, most importantly the strDir variable (which is a string representing the directory that holds all your CSVs)
Loop through the directory
Open each CSV
Copy the appropriate contents from each CSV
Paste the contents to the output workbook
Repeat the loop until all files have been iterated over
Hope this helps!
Option Explicit
Public Sub CombineCSVsInFolder()
Dim strFile As String, strDir As String
Dim wbkSource As Workbook, wbkOutput As Workbook
Dim wksSource As Worksheet, wksOutput As Worksheet
Dim lngLastRowSource As Long, lngLastRowOutput As Long
Dim rngSource As Range, rngOutput As Range
Dim blnFirst As Boolean
'Set references up-front
strDir = "c:\stack\my_csvs\" '<~ edit this line with the CSV directory
strFile = Dir(strDir)
blnFirst = True
Set wbkOutput = Workbooks.Add
Set wksOutput = wbkOutput.ActiveSheet
Application.ScreenUpdating = False
'Loop through the CSV directory
While (strFile <> "")
'Assign source CSV files
Set wbkSource = Workbooks.Open(strDir & strFile)
Set wksSource = wbkSource.ActiveSheet
'Assign boundaries of area to copy and output
lngLastRowSource = LastRowNum(wksSource)
lngLastRowOutput = LastRowNum(wksOutput)
With wksOutput
Set rngOutput = .Cells(lngLastRowOutput + 1, 1)
End With
'If this is the first time through, include headers, otherwise do not
If blnFirst = False Then
With wksSource
Set rngSource = .Range(.Cells(2, 1), .Cells(lngLastRowSource, 4))
End With
'Special case for first iteration to correct source and output ranges
Else
With wksSource
Set rngSource = .Range(.Cells(1, 1), .Cells(lngLastRowSource, 4))
End With
With wksOutput
Set rngOutput = .Cells(1, 1)
End With
blnFirst = False
End If
'Execute copy, close source and repeat
rngSource.Copy rngOutput
wbkSource.Close
strFile = Dir
Wend
'Turn screen updates back on
Application.ScreenUpdating = True
End Sub
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'INPUT : Sheet, the worksheet we'll search to find the last row
'OUTPUT : Long, the last occupied row
'SPECIAL CASE: if Sheet is empty, return 1
Public Function LastRowNum(Sheet As Worksheet) As Long
If Application.WorksheetFunction.CountA(Sheet.Cells) <> 0 Then
LastRowNum = Sheet.Cells.Find(What:="*", _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious).Row
Else
LastRowNum = 1
End If
End Function

Related

Importing data from multiple text files into Excel VBA [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I might have a question about VBA and Excel Macros. The thing that I need to do is to import data (actually integer values) from multiple text files that have random generated names (for example 12345678.txt, 8654321.txt, etc.) but which are stored in the same folder (let's call it Data folder) to excel into a column.
The problem that I face is that I have the same name for the measured values (called MVA) that are repeating over and over in the text files. I don't need all the data from the text files, only some specific rows of these MVA (for the example below let's say that I need only the MVA number for the "LED 01 Intensity" which is 6250 to be stored in a new cell in Excel. And I need to get that value that comes after "LED 01 Intensity" in the MVA row from 10 multiple text files (with random names that I don't know) to be stored each one in separate cells in Excel (from A1 to A10).
Example_____________________________________________________________________
Name: 153588.txt
Date: 14.05.2016
Name of product: Electronic Device 01
CHECK TEST
Resistance 101
MVA: 2 Ohm
MAX: 5 Ohm
MIN: 0 Ohm
PASS
LED 01 Intensity
MVA: 6250
MAX: 10000
MIN: 5000
PASS
I need a lot of these MVA values to be stored in Excel for analysis and I need to get an idea if this problem can be solved with VBA. If you can offer me some help to create a macro for this I would be thankful (I have basic knowledge of programming but I'm a beginner in VBA).
Here is the code I promised for. It is actually not only sample but actual code that you need according the descriptions you provided.
Please note I wrote it according to the sample file you provided - means that it might fail with different text file structures.
You will notice there is a settings section at the beginning. That's where you setup what needs to be given to the code.
It won't be a big impact for only hundreds of text files for your system considering the sample file - perhaps will work and finish in seconds. However screen updating might be disabled in the code during the code execution. See ScreenUpdating property of Excel Application object if you notice a real big system slowness.
I am hoping to give you some good start for the VBA, so I tried to use many methods and commented a lot to explain what we are doing in each step. For example, using the first worksheet as results worksheet in the newly created workbook but creating a new worksheet for the temporary worksheet. There is a reason for this: every new workbook is created with at least one worksheet but it might be also the only one worksheet according to the Excel settings in that computer. However, even those part could be designed different by getting the number of the worksheets first and delete the unnecessary ones and keep only 2 then use those instead creating a new one.
Shortly - there are many different ways to accomplish the same task - like in many other programming languages. For example, I used QueryTable to import data into the worksheet then used Find method to find out if it has the values I needed. I didn't have to do this, I could have instead put the all information in a string variable and make the search in the string! Or by using another method, or another.
Finally this is supposed to be what you need. And I hope it gives you a good start. To make this code work: Create a new workbook -> goto VBA -> Use menu and Insert->Module -> Copy and paste the following code into the right pane opened in the editor. Change the necessary variables in the settings area at the beginning in the sub procedure (likely only the path variable) and hit F5 to run the code.
Sub ImportData()
Dim wrk As Workbook
Dim shtSource As Worksheet
Dim shtResult As Worksheet
Dim rng As Range
Dim fndSection As Range
Dim fndValue As Range
Dim data As QueryTable
Dim strFile
Dim strPath As String
Dim strExt As String
Dim strSection As String
Dim strValue As String
' ======== BEGIN SETTINGS ========
' Define the files path - note there is a last backslash
strPath = "C:\Users\smozgur\Desktop\files\"
' Define file extension
strExt = "*.txt"
' Section to be find
strSection = "Led 01 Intensity"
' Cell value to be find after section
strValue = "MVA:"
' ======== END SETTINGS ========
' Create a new workbook to not mess with existing
Set wrk = Application.Workbooks.Add
With wrk
' Use first (or only) worksheet to store results
Set shtResult = .Worksheets(1)
' Create temp worksheet for reading text files
Set shtSource = .Worksheets.Add
End With
' Name the Results worksheet
' and put search value to indicate it in results
With shtResult
.Cells(1, 1).Value = strValue
.name = "Results"
End With
' Make file search with the given path & extension information
strFile = Dir(strPath & strExt, vbNormal)
' Dir function returns the first file name
' with the given extension in the given path
' if it is empty string then it means "no more file returned"
Do Until strFile = ""
' Create a query table buffer by using the file reference
' in the temp worksheet starting from cell A1
Set data = shtSource.QueryTables.Add(Connection:="TEXT;" & strPath & strFile, Destination:=shtSource.Cells(1, 1))
' Set up query table import properties
With data
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1)
.TextFileTrailingMinusNumbers = True
' Finally retrieve data from the file
.Refresh BackgroundQuery:=False
End With
' Now the file content is in the temp worksheet as rows
' Find the section string in the data as Cell
Set fndSection = data.ResultRange.Find(strSection)
If Not fndSection Is Nothing Then
' If section is found then search for the Value Name AFTER found section
Set fndValue = data.ResultRange.Find(strValue, fndSection)
If Not fndValue Is Nothing Then
' If Value Name is found then put it into the next available cell in Results worksheet
' by removing the Value Name, so it will be the value itself
shtResult.Cells(shtResult.Rows.Count, 1).End(xlUp).Offset(1).Value = Replace(fndValue, strValue, "")
End If
End If
With data
' Clear the query table range
.ResultRange.Delete
' Delete the query table so we can recreate it for the next file
.Delete
End With
' Search for the next file meets the given path and extension criteria
strFile = Dir
Loop
' Delete the temporary worksheet
' Make it silent disabling Application Alerts about deleting the worksheet
Application.DisplayAlerts = False
shtSource.Delete
' Enable Application Alerts back
Application.DisplayAlerts = True
End Sub
Enjoy VBA programming!
==================================
* EDIT FOR MULTIPLE SECTIONS *
Following code handles multiple sections in the source files.
Sub ImportData()
Dim wrk As Workbook
Dim shtSource As Worksheet
Dim shtResult As Worksheet
Dim rng As Range
Dim fndSection As Range
Dim fndNextSection As Range
Dim fndValue As Range
Dim data As QueryTable
Dim strFile
Dim strPath As String
Dim strExt As String
Dim strSection As String
Dim strSections
Dim strValue As String
Dim i As Integer
Dim indFileNames As Boolean
' ======== BEGIN SETTINGS ========
' Define the files path - note there is a last backslash
strPath = "C:\Users\smozgur\Desktop\files\"
' Define file extension
strExt = "*.txt"
' Sections to be find
strSections = Array("Led 01 Intensity", _
"Led 02 Intensity", _
"Led 03 Intensity", _
"Led 04 Intensity", _
"Led 05 Intensity")
' Cell value to be find after section
strValue = "MVA:"
' Indicate file names in the output?
indFileNames = True
' ======== END SETTINGS ========
' Create a new workbook to not mess with existing
Set wrk = Application.Workbooks.Add
With wrk
' Use first (or only) worksheet to store results
Set shtResult = .Worksheets(1)
' Create temp worksheet for reading text files
Set shtSource = .Worksheets.Add
End With
' Name the Results worksheet
' and put section headers to indicate their columns
With shtResult
With .Cells(1).Resize(, UBound(strSections) + 1)
.Value = strSections
.Resize(, UBound(strSections) + 1).Font.Bold = True
End With
If indFileNames = True Then
With .Cells(1, UBound(strSections) + 3)
.Value = "NOTES"
.Font.Bold = True
End With
End If
.name = "Results"
End With
' Make file search with given information
strFile = Dir(strPath & strExt, vbNormal)
' Dir function returns the first file name
' with the given extension in the given path
' if it is empty string then it means "no more file returned"
Do Until strFile = ""
' Create a query table buffer by using the file reference
' in the temp worksheet starting from cell A1
Set data = shtSource.QueryTables.Add(Connection:="TEXT;" & strPath & strFile, Destination:=shtSource.Cells(1, 1))
' Set up query table import properties
With data
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1)
.TextFileTrailingMinusNumbers = True
' Finally retrieve data from the file
.Refresh BackgroundQuery:=False
End With
' Now the file content is in the temp worksheet as rows
' Loop through requested sections
For i = 0 To UBound(strSections)
' Find the section string in the data as Cell
Set fndSection = data.ResultRange.Find(strSections(i))
If Not fndSection Is Nothing Then
' If section is found then search for the Value Name AFTER found section
Set fndValue = data.ResultRange.Find(strValue, fndSection)
If Not fndValue Is Nothing Then
' What if value doesn't exist in this section but it finds the next value in the next section
' We have to avoid that unless we are certainly sure each section MUST have the value
If i < UBound(strSections) Then
Set fndNextSection = data.ResultRange.Find(strSections(i + 1), fndSection)
Else
Set fndNextSection = shtSource.Cells(shtSource.Rows.Count)
End If
' Next available cell in the Results worksheet
Set rng = shtResult.Cells(shtResult.Rows.Count, i + 1).End(xlUp).Offset(1)
' Only use the value if found value belongs to the section
If fndValue.Row < fndNextSection.Row Then
' If Value Name is found then put it into the next available cell in Results worksheet
' by removing the Value Name, so it will be the value itself
rng.Value = Replace(fndValue, strValue, "")
Else
rng.Value = "N/A"
End If
End If
End If
Next i
If indFileNames = True Then
' Let's indicate which file we got this values
Set rng = shtResult.Cells(shtResult.Rows.Count, UBound(strSections) + 3).End(xlUp).Offset(1)
rng.Value = strFile
End If
With data
' Clear the query table range
.ResultRange.Delete
' Delete the query table so we can recreate it for the next file
.Delete
End With
' Search for the next file meets the given path and extension criteria
strFile = Dir
Loop
' Autofit columns in the Results worksheet
shtResult.Columns.AutoFit
' Delete the temporary worksheet
' Make it silent disabling Application Alerts about deleting the worksheet
Application.DisplayAlerts = False
shtSource.Delete
' Enable Application Alerts back
Application.DisplayAlerts = True
End Sub

How to import specific text from files in to excel?

I found this code by #Scott Holtzman and I need to tweek it a bit to match my needs. This code takes each line in a text file and puts it into seperate columns in an excel sheet(A1, B1, C1 and so on), each text file is stored in a seperate row(1,2,3 and so on). First i want it to only put text into the excel sheet if the line starts with a specific text, second i want it to only copy some of the text from each line into the excel sheet.
Sub ReadFilesIntoActiveSheet()
Dim fso As FileSystemObject
Dim folder As folder, file As file, FileText As TextStream
Dim TextLine As String, Items() As String
Dim i As Long, cl As Range
' Get a FileSystem object
Set fso = New FileSystemObject
' get the directory you want
Set folder = fso.GetFolder("D:\YourDirectory\")
Dim x As Long
x = 1 'to offset rows for each file
' Loop thru all files in the folder
For Each file In folder.Files
' set the starting point to write the data to
Set cl = ActiveSheet.Cells(x, 1)
' Open the file
Set FileText = file.OpenAsTextStream(ForReading)
Dim j As Long
j = 0 'to offset columsn for each line
' Read the file one line at a time
Do While Not FileText.AtEndOfStream
TextLine = FileText.ReadLine 'read line
cl.Offset(, j).Value = TextLine 'fill cell
j = j + 1
Loop
' Clean up
FileText.Close
x = x + 1
Next file
Set FileText = Nothing
Set file = Nothing
Set folder = Nothing
Set fso = Nothing
End Sub
Here is what my text files look like:
From:NameName 'want all text except the "FROM:"
Date:yyyy.mm.dd 'want all text except the "Date:"
Type: XXXXXXXXX ' I don't want this line into excel
To: namename ' I don't want this line into excel
----------------------------- xxxxxxx ---------------------
A1: Tnr xxxxxxxxxxxxx 'want all text except the "A1: Tnr" only next 13char
A2: texttext 'want all text except the "A2:"
An: 'A1 and up to A14
A14: texttext 'want all text except the "A14:"
------------------------------ xxxxxx ----------------------
So in total there is 22 lines in the text file.
And if it is possible to use the FROM:, DATE:, A1: to A14: as headers in the first row that would be epic.
have tried to google my way to it, and tried a bit with this:
TextLine = FileText.ReadLine 'read line
If InStr(TextLine, "A1:")
but that works only for one line and i cant seem to get it to work with several lines. In addition it puts the output in cell F1, instead of A1. think this is since each line in text document gets one cell - even if nothing is written to it.
Here is a solution that fills one row in the Excel sheet per file, starting at row 2. You should manually fill in the titles in that first row as follows:
From | Date | A1 | A2 | ... | A14
The lines that you are not interested in are skipped, and the values are put in the correct columns:
Sub ReadFilesIntoActiveSheet()
Dim fso As FileSystemObject
Dim folder As folder, file As file, FileText As TextStream
Dim TextLine As String
Dim cl As Range
Dim num As Long ' numerical part of key, as in "Ann:"
Dim col As Long ' target column in Excel sheet
Dim key As String ' Part before ":"
Dim value As String ' Part after ":"
' Get a FileSystem object
Set fso = New FileSystemObject
' Get the directory you want
Set folder = fso.GetFolder("D:\YourDirectory\")
' Set the starting point to write the data to
' Don't write in first row where titles are
Set cl = ActiveSheet.Cells(2, 1)
' Loop thru all files in the folder
For Each file In folder.Files
' Open the file
Set FileText = file.OpenAsTextStream(ForReading)
' Read the file one line at a time
Do While Not FileText.AtEndOfStream
TextLine = FileText.ReadLine 'read line
key = Split(TextLine & ":", ":")(0)
value = Trim(Mid(TextLine, Len(key)+2))
num = Val(Mid(key,2))
If num Then key = Replace(key, num, "") ' Remove number from key
col = 0
If key = "From" Then col = 1
If key = "Date" Then col = 2
If key = "A" Then col = 2 + num
If col Then
cl.Offset(, col-1).Value = value ' Fill cell
End If
Loop
' Clean up
FileText.Close
' Next row
Set cl = cl.Offset(1)
Next file
End Sub
The above code will work well even if items are missing in your file, like if the line with "A12:" would not be present, this will leave the corresponding cell in the sheet empty, instead of putting the value of "A13:" there, causing a shift.
Even if the order of the lines would change, and "From:" would appear after "Date:", this will not have a negative effect in the output. "From" values will always get into the first column, "Date" values in the second, etc.
Also, if your file would contain many other lines with differing formats, they will all be ignored.
Replace the "Do While's" body with the following lines
TextLine = FileText.ReadLine 'read line
If Not (Left(TextLine, 1) = "T" Or Left(TextLine, 1) = "-") Then
TextLine = Trim(Mid(TextLine, InStr(TextLine, ":") + 1))
If (TextLine <> "") Then
cl.Offset(, j).Value = TextLine 'fill cell
j = j + 1
End If
End If

DIR Not Functioning Correctly

I am using VBA to import data from .txt files into a table of my spreadsheet which I am using for further pivot charts. The network directory that I am importing the files from contains ~5500 files and will grow over time at about 2000 files per year currently. The entries in the table are sorted by date (oldest to newest).
I have a macro which checks the date of the most recent entry, then uses DIR to search the network location and iterate through the files in that directory. For each file, if the file is newer than the most recent entry, I want to import the data and add it to the table. If the file is older, I want DIR to move to the next file. Below is the code I am currently using.
Sub NewFilesFromNetwork()
Dim myDatabase As Worksheet
Set myDatabase = Sheets("Database")
Dim TotalRows As Long, LastDate As Date
TotalRows = myDatabase.ListObjects("Table1").Range.Rows.Count
LastDate = Cells(TotalRows + 48, 6).Value 'the "+48" here is important because there are 48 hidden rows at the top of the spreadsheet before the table starts
Dim MyFolder As String, MyFile As String
On Error Resume Next
Application.ScreenUpdating = False
MyFolder = "*path to my network location*"
MyFile = Dir(MyFolder & "*.txt")
Dim t As Integer, k As Integer
t = 0 'counter for calculating total files imported
k = 0 'counter for calculating total files checked
Do While MyFile <> ""
TxtFile = MyFolder & MyFile
If FileDateTime(TxtFile) > LastDate Then
Open TxtFile For Input As #1
Do Until EOF(1)
Line Input #1, textline
text = text & textline
Loop
Close #1
Call CommonImportCode 'separate sub which picks out information from the .txt file string and adds it to the table as a new entry
k = k + 1
t = t + 1
MyFile = Dir()
End If
k = k + 1
MyFile = Dir()
Loop
Application.ScreenUpdating = True
MsgBox "Number of files searched = " & k & vbNewLine & "Number of files imported = " & t
End Sub
The issue I am having is this:
I can check the network location and see that there are 10 new files. However, the macro only imports 5 of them, and seems to be importing only every other file of the new files. Is there a reason the macro is skipping files when they meet the conditions of the IF statement?
k = k + 1
MyFile = Dir()
That code is duplicated. If your "If" just above is true, you are jumping one file. Your loop should be :
Do While MyFile <> ""
TxtFile = MyFolder & MyFile
If FileDateTime(TxtFile) > LastDate Then
Open TxtFile For Input As #1
Do Until EOF(1)
Line Input #1, textline
text = text & textline
Loop
Close #1
Call CommonImportCode 'separate sub which picks out information from the .txt file string and adds it to the table as a new entry
t = t + 1
End If
k = k + 1
MyFile = Dir()
Loop
or something approaching.

Embed Excel VBA script in Powershell Script

I wrote a Powershell script that queries all of my groups from Exchange Online, then gets membership for each of those groups and saves each group to a separate CSV file. This is all working fine.
(Some non relevant parts omitted for brevity):
$excelTemplate = "$($fileLocation)\group-breakout.xlsm"
Copy-Item $excelTemplate "$($tempPath)\group-breakout-$($curDate).xlsm"
# Creating Excel COM Object
$excel = new-object -comobject excel.application
$excelFile = Get-ChildItem -Path C:\temp\group-breakout -Include *.xlsm -Recurse
# Gathering all groups:
Write-Host "Getting all groups from Exchange Online..."
$allGroups = Get-DistributionGroup | select Name, PrimarySmtpAddress, ManagedBy, MemberJoinRestriction
$allGroups | Export-Csv "$($tempPath)\1-AllGroups.csv" -NoTypeInformation
Write-Host "`tDone."
# Gathering members for all groups
Write-Host "Getting members for all groups from Exchange Online..."
$allGroups | ForEach-Object {
Get-DistributionGroupMember -Identity $_.Name | select DisplayName, Alias, PrimarySmtpAddress | Export-Csv "$($tempPath)\$($_.name.Replace("/","-")).csv" -NoTypeInformation
}
Write-Host "`tDone."
# Calling macro in xlsm to merge the created csvs into a Excel spreadsheet
Write-Host "Creating Spreadsheet..."
$workbook = $excel.workbooks.open($excelFile) # Opening workbook
$worksheet = $workbook.worksheets.item(1) # Selecting worksheet
$excel.Run("ImportCSVs") # Calling macro
$workbook.save() #Saving workbook
$workbook.close() # Closing workbook
$excel.quit() # Closing Excel COM Object
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null # Making sure Excel process is closed.
I also have an Excel VBA script access through a COM object that will take those CSVs and add them to an XLSX with each CSV being one worksheet:
Sub ImportCSVs()
Dim fPath As String
Dim fCSV As String
Dim wbCSV As Workbook
Dim wbMST As Workbook
Set wbMST = ThisWorkbook
fPath = "C:\temp\group-breakout\" 'path to CSV files, include the final \
Application.ScreenUpdating = False 'speed up macro
Application.DisplayAlerts = False 'no error messages, take default answers
fCSV = Dir(fPath & "*.csv") 'start the CSV file listing
On Error Resume Next
Do While Len(fCSV) > 0
Set wbCSV = Workbooks.Open(fPath & fCSV) 'open a CSV file
wbMST.Sheets(ActiveSheet.Name).Delete 'delete sheet if it exists
ActiveSheet.Move After:=wbMST.Sheets(wbMST.Sheets.Count) 'move new sheet into Mstr
Columns.AutoFit 'clean up display
fCSV = Dir 'ready next CSV
Loop
Worksheets("1-AllGroups").Activate
Worksheets("placeholder").Delete
Workbooks.Application.ActiveWorkbook.SaveAs Filename:="C:\temp\group-breakout\group-breakout.xlsx", FileFormat:=51
Application.ScreenUpdating = True
Set wbCSV = Nothing
End Sub
The issue I have is having to include the Excel macro-enabled spreadsheet in the script location so I can access it from the script. Is there a way to somehow embed the VBA script in the Powershell script and run it inside of Excel? Or, alternatively, a way to perform the tasks in the VBA script using Powershell directly?

Read file without opening and delete it

I'm trying to figure out a way to read the first line of text in a .txt through excel VBA without opening the file, something I've been having trouble finding since all the examples I've seen involve opening the .txt one way or another.
Aside from this, I was wondering if there was any way for me to get the VBA code to delete the mentioned .txt a set time after excel has been closed... which I'm not too sure is even remotely possible (with VBA at least).
EDIT:
The simplified code goes like this:
Option Explicit
Public g_strVar As String
Sub Test_Proc()
Dim row as Long
row = 2
Do While Cells(row, 1) <> ""
Cells(row, 2) = ImportVariable(Cells(row, 1))
row = row + 1
Loop
End Sub
Function ImportVariable(strFile As String) As String
Open strFile For Input As #1
Line Input #1, ImportVariable
Close #1
End Function
Column 1 contains the locations of each and every .txt file, and on the column next to it I have to detail what is the first line of text on each file. Problem is that the list has been in a couple occasions about 10K long, and the only place I can think of from where I can improve on the time this takes to execute is in the "Open / Close" since some of these .txt files are 12.000 KB in size and take a bit to open.
This might be faster than opening each file (reads first line from a 18.5 Mb file in 0.1953125 sec)
Option Explicit
Dim cmdLine As Object
Sub Test_Proc()
Dim i As Long, minRow As Long, maxRow As Long, rng1 As Range, rng2 As Range
Dim t As Double, ws As Worksheet, x As Variant, col1 As Variant, col2 As Variant
Set ws = ThisWorkbook.Worksheets(1)
minRow = 2
With ws
.Columns(2).Delete
maxRow = .UsedRange.Rows.Count
Set rng1 = .Range("A1:A" & maxRow)
Set rng2 = .Range("B1:B" & maxRow)
End With
col1 = rng1.Value2: col2 = rng2.Value2
Set cmdLine = CreateObject("WScript.Shell")
Application.ScreenUpdating = False
t = Timer
For i = minRow To maxRow
If Len(col1(i, 1)) > 0 Then
ws.Cells(i, 2).Value2 = Replace(ImportLine(col1(i, 1)), vbCrLf, vbNullString)
End If
Next
'rng2.Value2 = col2
Application.ScreenUpdating = True
InputBox "Duration: ", "Duration", Timer - t '18.5 Mb file in 0.1953125 sec
End Sub
Function ImportLine(ByVal strFile As String) As String
ImportLine = Replace(cmdLine.Exec( _
"%comspec% /C FindStr /N . " & strFile & " | FindStr ^1:" _
).STDOut.ReadAll, "1:", vbNullString)
End Function
A bit nested but it does the following:
CMD /C - opens a command line window, then closes it when completed
FindStr /N . C:\test.txt - Find any character, and output the line with line number in format "1:"
| FindStr ^1: - redirect to another FindStr that uses regex to find "1:" at start of line
When the command line is completed, return the output to the Replace function
Replace removes "1:" and returns the string
If your files might contain the string "1:" somewhere else within the first line
we can use the Right() function: return Right(output, Len(output)-2)
or we can use a different command line that numbers the lines with "[1]":
Find /N " " C:\test.txt | Find "[1]"