I currently have to code a script for my work that deletes the complete row if column D is empty in a .csv file with vbs.
I found a solution that might work thought I struggle a bit tbh.
enter Const xlUp = -4162 ' Excel variables are not defined in vbscript
'Set objFile = objFSO.OpenTextFile("Testexport_neu.csv", ForReading) 'Datei Quelle
Dim oBook : Set oBook = objFile
Dim oSheet : Set oSheet = oBook.Sheets(1)
Dim iLastRow, iRow
iLastRow = oSheet.Cells(oSheet.Rows.Count, 3).End(xlUp).Row
For iRow = iLastRow to 1 Step -1 'assumes a header row otherwise use 1 instead of 2
If oSheet.Range("D" & iRow) = "" Then
oSheet.Range("D" & iRow).EntireRow.Delete ' delete row if blank
End If
Code by User Dave
now to my problem, as I can't find any helpful documentation I have no clue on how to implement the .csv file the right way. ... or what the oXYZ methods do...
Thanks for any advice
As to why I haven't commented on the original post where Dave put this code on, as this post was made in 2018 I wasn't sure if I revive any answers there tbh
Does it have to be VBScript ?
Is your data really CSV (text based), like this ? Post a small example, it would help greatly.
COLA;COLB;COLC;COLD;COLE;COLF
AAA;BBB;CCC;DDD;EEE;FFF
A2;B2;C2;;E2;F2 <<<< left out
A3;B3;C3;D3;E3;F3
The job would be trivial to do with AWK: split the lines (just set separator) then check if column D is empty, if NOT then print the entire line.
Effectively this will do what you ask for: filter out lines with empty column D. Not by deleting it, but by outputting everything else. I will edit this post later with an example. AWK is a free program available for pretty much every OS out there.
Same can be done with other tools.
Btw, you seem to handle a CSV file like an Excel document, accessing Excel features. Excel wants Windows to believe CSV is actually an Excel sheet, when it's just text. This can lead to several unwanted effects as Excel tries to be "clever" on your behalf.
Related
I am having a most frustrating time time with the DoCmd.TransferSpreadsheet method. I have a workbook with multiple worksheets in which users are updating data and I have a script that puts all the records back into a single sheet, links the spreadsheet, and updates the data in my Access DB. My problem is in the Range parameter. I pass the following string and get the following error:
DoCmd.TransferSpreadsheet TransferType:=acLink, SpreadsheetType:=acSpreadsheetTypeExcel12Xml, _
TableName:=linkSheet, fileName:=Wb.Path & "\" & Wb.name, _
HasFieldNames:=True, Range:="AccessUpdate!updateTable"
The Microsoft Access database engine could not find the object 'AccessUpdate$updateTable'. Make sure the object exists and that you spell its name and the path name correctly. If 'Access_Update$updateTable' is not a local object, check your network connection or contact the server administrator.
I can't seem to understand why it substitutes the dollar sign for the bang. Any other help in understanding how to specify the range would also be appreciated.
Thanks!
I know this is an year old question but it is an almost timeless problem.
I'm trying to do the same from the Excel side and bumping into the same problem. Access switching the sheet separator "!" for "$"
I found that this is a bug from Access 2000 that was never corrected. Or better, it was partially corrected at some point. So depending on your Access build and the size of the range [yes, size, since this is a bug from Access 2000] the solutions provided by Cisco or HansUp will work.
Another sources explaining the problem and a similar solution is provided by the MS$ themselves
https://answers.microsoft.com/en-us/office/forum/office_2007-access/transferspreadsheet-error-3011-can-not-file-sheet/980b2dc1-9ee1-4b3e-9c3c-a810f1428496
with the help of Bob Larson Former Access MVP (2008-2010) [see his very last post]
Now, if your range is on a different sheet with more than 65536 rows, this bug will come back.
See here for reference
Funny enough, if this is Sheet1 [yes, index 1 of all sheets] it will work with any range size. But any other sheet it wil fail.
This was my original range: BASE!A2:X68506, named REF_ACCESS. BASE is my Sheet5. Access 2010 & Excel 2010
I tried ActivateSheet, assign to string inside command, assign to string outside command, replace(,"$","!""), nothing worked. Even on Office 2016 from a friend
If I use "BASE!A2:X64506", it works. If I use "A2:X68506", Access assumes Sheet1 and works. Attention that all ranges do not have "$", but I guess you already know that
My last test was something like this monster
DoCmd.TransferSpreadsheet TransferType:=acImport, SpreadsheetType:=9, TableName:="TEST", Filename:=ThisWorkbook.FullName, HasFieldNames:=False, Range:=Worksheets("BASE").Name & "!" & Replace(Left(Worksheets("BASE").Range("REF_ACCESS").Address, Len(Worksheets("BASE").Range("REF_ACCESS").Address) - 1), "$", "")
A test that using my range within the 65536 row limit [6553 to be precise] would work. And it did.
So I see solutions with only two options for now. Either copy your range to Sheet1 or another sheet, as RyanM did, or divide your range in multiple DoCmd with 65536 rows.
I know it is long. Sorry, this was 2 full days looking for an answer without any real solution. I hope this helps other people with the same problem.
I tried multiple methods for getting around this without making major modifications to my code but with no avail. I did come up with a solution but it is rather resource intensive and messy. However, in case someone has a similar issue, I will post it here. I wound up separating my update sheet into it's own file from the rest of the workbook and linking that file. This prevented Access from trying to link a different sheet and got me around the whole Range issue. I know it's not elegant or efficient but it worked. If I figure out a cleaner way I'll post it here.
Set xl = Wb.Parent
xl.ScreenUpdating = False
xl.DisplayAlerts = False
strFile = mypath & "\TempIss.xlsx"
For i = 1 To Wb.Worksheets.count
If InStr(1, Wb.Worksheets(i).name, "Update", vbTextCompare) > 0 Then
tableId = i
Exit For
End If
Next i
If tableId = 0 Then
MsgBox "This workbook does not seem to have the necessary worksheet for updating " & _
"the Participant Issues Log in Access.", vbInformation, "Uh oh..."
Exit Function
Else
Set upWs = Wb.Worksheets(i)
upWs.Select
upWs.Copy
xl.ActiveSheet.SaveAs fileName:=strFile
xl.ActiveWorkbook.Close
Call rmSheet(Wb, "AccessUpdate")
xl.ScreenUpdating = True
linkSheet = "tempIssLog"
DoCmd.TransferSpreadsheet TransferType:=acImport, SpreadsheetType:=acSpreadsheetTypeExcel12Xml, _
TableName:=linkSheet, fileName:=strFile, _
HasFieldNames:=True
Kill (strFile)
If the range is a named range (in Excel) follow the instruction above (HansUp comment).
If the range is defined in MS-Access be sure to pass a string (something like "A1:G12") and not the control name.
Dim StrRange as variant
Dim NameofMySheet as string
NameofMySheet = "xxxxxx" ' <- Put here the name of your Excel Sheet
StrRange = NameofMySheet & "!" & "A1:G12"
DoCmd.TransferSpreadsheet TransferType:=acLink, SpreadsheetType:=acSpreadsheetTypeExcel12Xml, _
TableName:=linkSheet, fileName:=Wb.Path & "\" & Wb.name, _
HasFieldNames:=True, Range:= StrRange
Note 1: StrRange with no quotes!
how can I make the 'Hi' write to a new column (but same row) in CSV? I thought the comma should do the trick but it doesn't.
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objLogFile = objFSO.CreateTextFile("test.csv", _
ForWriting, True)
objLogFile.Write "Hello,"
objLogFile.Write "Hi"
objLogFile.Writeline
The comma has nothing to do with it. The Write leaves the current position on the same line, and the WriteLine moves it to the next line. So your script produces this:
Hello,Hi
which, I presume, is what you want.
Just in case your real problem is that the application you use to view test.csv shows Hello,Hi in one cell: You need to tell that application to use comma as field separator.
I have written a simple web service that returns large volumes of csv data. I will to import this into Excel in a tabular format using Excel's "Data From Web" function.
Is there a way to get Excel to automatically parse the csv fields returned into individual columns as part of the import operation?
At present the only means I have for doing this is to first import the data into a single column and then write VBA code to select the data and split it using TextToColumns. This feels messy / error-prone.
The other alternative I have is to modify the web server to serve back the data as HTML. However, I'm reluctant to do this as adding tags around each csv field will greatly impact the volume of data returned.
Adamski,
Here is something that I use. I found the core somewhere on the internet, but don't know where.
What it does is it opens a tab separated file and reads the data in an excel sheet
If Answer1 = vbYes Then 'I asked prior if to import a tab separated file
Sheets("ZHRNL111").Select 'Select the sheet to dump the data
On Error Resume Next
With ActiveSheet
If .AutoFilterMode Then .ShowAllData 'undo any autofilters
End With
Sheets("ZHRNL111").Cells.Clear 'remove any previous data
On Error GoTo 0
Range("A1").CurrentRegion.Delete
Fname = MyPath & "\LatestReports\Report-111.tsv"
Open Fname For Input As #1
iRow = 1
Line Input #1, Record
On Error Resume Next
Do Until EOF(1)
P = Split(Record, vbTab)
For iCol = 1 To 14
Cells(iRow, iCol) = P(iCol - 1)
Next iCol
iRow = iRow + 1
Line Input #1, Record
Loop
On Error GoTo 0
Close 1
End If
Regards,
Robert Ilbrink
Depending on the version of excel you are running you should be able to open the .csv in excel and use the text to columns feature built into excel.
Also, if you could modify your csv to split columns based on commas "," instead of tabs excel would open it directly without the need to format it.
I know however this can sometimes be a problem depending on the data you are importing because if the data contains a comma it must be inside quotations.
In my experience the best way is to use quotations on every field if possible.
Hope this helps.
I am actually creating a product right now to do this in both XML and JSON for Excel. I know comma delimited does work in Excel, with some caveats. One way around it is to put some "" around the text in between the delimiters for the "Data From Web" feature. There are still issues with that however. I did find that despite it's increased size, XML was the best option for quick turn around. I was able to create the service and hand my project manager the Excel document which he could update at anytime.
I have a table in MS Access, which has the following data to be exported to excel
Release numbers
Test cases
Results
After exporting to Excel I want to have distinct release numbers as rows starting from A2 and distinct test case name as columns starting from B1. There might be couple thousands records. Then each cell will be set to result tag. Additionally will need some fancy coloring/bordering stuff.
The question - is it possible to do this using VBA in Access and if yes what is the way to go? Any hint, sample, example, resource would be appreciated... I've googled but the most thing I came accross is DoCmd.TransferSpreadsheet or DoCmd.OutputTo which I believe will not do what I want. Saw some examples with CreateObject("Excel.Application") but not sure what are limitations and performance using this way.
I don't know if it would work for your case, but you might try adding the VBA code to an Excel document rather than the Access database. Then you could refresh the data from the Excel file and add the formatting there much easier. Here is one example:
http://www.exceltip.com/st/Import_data_from_Access_to_Excel_%28ADO%29_using_VBA_in_Microsoft_Excel/427.html
(Or see other examples at http://www.exceltip.com/exceltips.php?view=category&ID=213)
Again, it may not work for your case, but it may be an option to consider. Essentially, instead of pushing from Access, you would pull from Excel.
Yes, there are many cases when the DoCmd.TransferSpreadsheet command is inadaquate.
The easiest way is to reference the Excel xx.x Object model within Access (Early Binding). Create and test your vba export function that way. Then once you are satisfied with your output, remove the Excel object model reference, then change your objects to use use Late Binding using CreateObject. This allows you to easily have other machines that are using different versions of Excel/Access to use it just the same.
Here is a quick example:
Sub ExportRecordsetToExcel(outputPath As String, rs As ADODB.Recordset)
'exports the past due report in correct formattig to the specified path
On Error GoTo handler:
Const xlUP As Long = -4162 'excel constants if used need to be referenced manually!
Dim oExcel As Object
Dim oBook As Object
Dim oSheet As Object
Dim row As Long
If rs.BOF And rs.EOF Then
Exit Sub 'no data to write
Else
rs.MoveFirst
End If
row = 1
Set oExcel = CreateObject("Excel.Application")
oExcel.Visible = False 'toggle for debugging
Set oBook = oExcel.Workbooks.Add 'default workbook has 3 sheets
'Add data to cells of the first worksheet in the new workbook.
Set oSheet = oBook.worksheets(1)
Do While rs.EOF = False
oSheet.range("A" & row).value = rs.Fields("MyField").value
'increase row
row = row + 1
Loop
oBook.SaveAs (outputPath)
'tidy up, dont leave open excel process
Set oSheet = Nothing
Set oBook = Nothing
oExcel.Quit
Set oExcel = Nothing
Exit Sub
handler:
'clean up all objects to not leave hanging processes
End Sub
All -
I'm embarrassed to ask something that appears to be so rudimentary, but I'm stuck.
Using Access 2007, I ran a query against a single 84K row table to produce a result set of ~80K row. I can't copy/paste the result set into Excel (Access fails copy/pasting > 64K rows). When I right-click on the query and export, no matter what format I try, it only exports the first row (ID).
How can I get Access to export the entire result set? (I've tried highlighting everything, etc. I also tried using the 'External Data' ribbon, but that just exports the original table, not the result set from the query I ran.)
Thanks!
I ran a query, highlighted everything by clicking on the little arrow in the upper left, CTRL-C, opened Excel, CTRL-V. Exported the whole thing. (Granted I didn't have ~100k rows like you, but I don't understand why it wouldn't handle that too.)
Or is that not what you want?
What if you copy 40,000 rows at a time to different tabs in your Excel file?
I have had a similar problem with Access 2013, so decided to share how to resolve it. The only way I could solve this issue was by using VBA.
Only update testSQL (easy to see when you go to SQL view of your query) and CSV_file_path (the file path of your CSV export)
Sub Export_ToCSV()
Dim testSQL As String
Dim UserInput As String
Dim db As Database, qd As DAO.QueryDef
Set db = CurrentDb
testSQL = "SELECT Table1.Column1, Table1.Column2, Table1.Column3 FROM Table1;"
CSV_file_path = "C:\temp\filename.csv"
Set qd = db.CreateQueryDef("tmpExport", testSQL)
DoCmd.TransferText acExportDelim, , "tmpExport", CSV_file_path, True
db.QueryDefs.Delete "tmpExport"
MsgBox ("Finished")
End Sub