I have a CSV file with 550,000+ rows.
I need to import this data into Access, but when I try it throws an error that the file is too large (1.7GB).
Can you recommend a way to get this file into Access?
Try linking instead of importing ("get external data" -> "link table" in 2003), that leaves the data in the CSV-file and reads from the file directly and in-place. It doesn't limit size (at least not anywhere near 1.7 GB). It may limit some of your read/update operations, but it will at least get you started.
I'd either try the CSV ODBC connector, or otherwise import it first in a less limited database (MySQL, SQL Server) and import it from there.
It seems that some versions of access have a hard 2GB limit on MDB files so you might get into trouble with that anyway.
Good luck.
You can also use an ETL tool. Kettle is an open source one (http://kettle.pentaho.org/) and really quite easy to use. To import a file into a database requires a single transformation with 2 steps: CSV Text Input and Table Output.
why do you using access for huge files ? use sqlexpress or firebird instead
I remember that Access has some size limitation around 2 Go. Going to free SQLExpress (limited to 4 Go) or free MySQL (no size limitation) could be easier.
Another option would be to do away with the standard import functions and write your own. I have done this one time before when some specific logic needed to be applied to the data before import. The basic structure is……
Open then file
Get the first line
Loop through until the end of the line
If we find a comma then move onto the next field
Put record into database
Get the next line repeat etc
I wrapped it up into a transaction that committed every 100 rows as I found that improved performance in my case but it would depend on your data if that helped.
However I would say that linking the data as others have said is the best solution, this is just an option if you absolutely have to have the data in access
Access creates a lot of overhead so even relatively small data sets can bloat the file to 2GB, and then it will shut down. Here are a couple of straightforward ways of doing the import. I didn't test this on huge files, but these concepts will definitely work on regular files.
Import data from a closed workbook (ADO)
If you want to import a lot of data from a closed workbook you can do this with ADO and the macro below. If you want to retrieve data from another worksheet than the first worksheet in the closed workbook, you have to refer to a user defined named range. The macro below can be used like this (in Excel 2000 or later):
GetDataFromClosedWorkbook "C:\FolderName\WorkbookName.xls", "A1:B21", ActiveCell, False
GetDataFromClosedWorkbook "C:\FolderName\WorkbookName.xls", "MyDataRange", Range ("B3"), True
Sub GetDataFromClosedWorkbook(SourceFile As String, SourceRange As String, _
TargetRange As Range, IncludeFieldNames As Boolean)
' requires a reference to the Microsoft ActiveX Data Objects library
' if SourceRange is a range reference:
' this will return data from the first worksheet in SourceFile
' if SourceRange is a defined name reference:
' this will return data from any worksheet in SourceFile
' SourceRange must include the range headers
'
Dim dbConnection As ADODB.Connection, rs As ADODB.Recordset
Dim dbConnectionString As String
Dim TargetCell As Range, i As Integer
dbConnectionString = "DRIVER={Microsoft Excel Driver (*.xls)};" & _
"ReadOnly=1;DBQ=" & SourceFile
Set dbConnection = New ADODB.Connection
On Error GoTo InvalidInput
dbConnection.Open dbConnectionString ' open the database connection
Set rs = dbConnection.Execute("[" & SourceRange & "]")
Set TargetCell = TargetRange.Cells(1, 1)
If IncludeFieldNames Then
For i = 0 To rs.Fields.Count - 1
TargetCell.Offset(0, i).Formula = rs.Fields(i).Name
Next i
Set TargetCell = TargetCell.Offset(1, 0)
End If
TargetCell.CopyFromRecordset rs
rs.Close
dbConnection.Close ' close the database connection
Set TargetCell = Nothing
Set rs = Nothing
Set dbConnection = Nothing
On Error GoTo 0
Exit Sub
InvalidInput:
MsgBox "The source file or source range is invalid!", _
vbExclamation, "Get data from closed workbook"
End Sub
Another method that doesn't use the CopyFromRecordSet-method
With the macro below you can perform the import and have better control over the results returned from the RecordSet.
Sub TestReadDataFromWorkbook()
' fills data from a closed workbook in at the active cell
Dim tArray As Variant, r As Long, c As Long
tArray = ReadDataFromWorkbook("C:\FolderName\SourceWbName.xls", "A1:B21")
' without using the transpose function
For r = LBound(tArray, 2) To UBound(tArray, 2)
For c = LBound(tArray, 1) To UBound(tArray, 1)
ActiveCell.Offset(r, c).Formula = tArray(c, r)
Next c
Next r
' using the transpose function (has limitations)
' tArray = Application.WorksheetFunction.Transpose(tArray)
' For r = LBound(tArray, 1) To UBound(tArray, 1)
' For c = LBound(tArray, 2) To UBound(tArray, 2)
' ActiveCell.Offset(r - 1, c - 1).Formula = tArray(r, c)
' Next c
' Next r
End Sub
Private Function ReadDataFromWorkbook(SourceFile As String, SourceRange As String) As Variant
' requires a reference to the Microsoft ActiveX Data Objects library
' if SourceRange is a range reference:
' this function can only return data from the first worksheet in SourceFile
' if SourceRange is a defined name reference:
' this function can return data from any worksheet in SourceFile
' SourceRange must include the range headers
' examples:
' varRecordSetData = ReadDataFromWorkbook("C:\FolderName\SourceWbName.xls", "A1:A21")
' varRecordSetData = ReadDataFromWorkbook("C:\FolderName\SourceWbName.xls", "A1:B21")
' varRecordSetData = ReadDataFromWorkbook("C:\FolderName\SourceWbName.xls", "DefinedRangeName")
Dim dbConnection As ADODB.Connection, rs As ADODB.Recordset
Dim dbConnectionString As String
dbConnectionString = "DRIVER={Microsoft Excel Driver (*.xls)};ReadOnly=1;DBQ=" & SourceFile
Set dbConnection = New ADODB.Connection
On Error GoTo InvalidInput
dbConnection.Open dbConnectionString ' open the database connection
Set rs = dbConnection.Execute("[" & SourceRange & "]")
On Error GoTo 0
ReadDataFromWorkbook = rs.GetRows ' returns a two dim array with all records in rs
rs.Close
dbConnection.Close ' close the database connection
Set rs = Nothing
Set dbConnection = Nothing
On Error GoTo 0
Exit Function
InvalidInput:
MsgBox "The source file or source range is invalid!", vbExclamation, "Get data from closed workbook"
Set rs = Nothing
Set dbConnection = Nothing
End Function
For really large files, you can try something like this . . .
INSERT INTO [Table] (Column1, Column2)
SELECT *
FROM [Excel 12.0 Xml;HDR=No;Database=C:\your_path\excel.xlsx].[SHEET1$];
OR
SELECT * INTO [NewTable]
FROM [Excel 12.0 Xml;HDR=No;Database=C:\your_path\excel.xlsx].[SHEET1$];
Related
I have requirements as below :
There is a folder named BATCH inside D:// drive of my PC.
Now this D://BATCH contains excel files with any random names. Every excel file has only one record.
I have to create .exe file or any Desktop Application which lets the user to browse the BATCH folder and then can upload the content or data from the excel files to our Server. We have to put the excel data into JSON and then have to upload it to the server.
One more thing is that If I have uploaded data from 3 files and then again user tries to upload by selecting the folder, data which are new or not uploaded only those data should be upload. The data in BATCH folder is generating daily with connected machine.
My background is for Web and Mobile development. So, little bit confused of achieving this thing as explained above.
So, How can I achieve this? Which technology I have to use or which are the tools that can be useful?
Thanks for the support.
There are probably a bunch of ways to skin this cat. Maybe import everything from all Excel files in the folder into one single Excel file, and export this to SQL Server. Just a thought.
Sub InsertInto()
'Declare some variables
Dim cnn As adodb.Connection
Dim cmd As adodb.Command
Dim strSQL As String
'Create a new Connection object
Set cnn = New adodb.Connection
'Set the connection string
cnn.ConnectionString = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=Northwind;Data Source=Server_Name"
'Create a new Command object
Set cmd = New adodb.Command
'Open the Connection to the database
cnn.Open
'Associate the command with the connection
cmd.ActiveConnection = cnn
'Tell the Command we are giving it a bit of SQL to run, not a stored procedure
cmd.CommandType = adCmdText
'Create the SQL
strSQL = "UPDATE TBL SET JOIN_DT = '2019-12-10' WHERE EMPID = 2"
'Pass the SQL to the Command object
cmd.CommandText = strSQL
'Execute the bit of SQL to update the database
cmd.Execute
'Close the connection again
cnn.Close
'Remove the objects
Set cmd = Nothing
Set cnn = Nothing
End Sub
Just to embellish my original answer a bit...you can easily import data from multiple excel files in a folder, into one single Excel file, using a concept like the one below.
Sub Basic_Example_1()
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String
Dim SourceRcount As Long, Fnum As Long
Dim mybook As Workbook, BaseWks As Worksheet
Dim sourceRange As Range, destrange As Range
Dim rnum As Long, CalcMode As Long
'Fill in the path\folder where the files are
MyPath = "C:\Users\Ron\test"
'Add a slash at the end if the user forget it
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
'If there are no Excel files in the folder exit the sub
FilesInPath = Dir(MyPath & "*.xl*")
If FilesInPath = "" Then
MsgBox "No files found"
Exit Sub
End If
'Fill the array(myFiles)with the list of Excel files in the folder
Fnum = 0
Do While FilesInPath <> ""
Fnum = Fnum + 1
ReDim Preserve MyFiles(1 To Fnum)
MyFiles(Fnum) = FilesInPath
FilesInPath = Dir()
Loop
'Change ScreenUpdating, Calculation and EnableEvents
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
'Add a new workbook with one sheet
Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
rnum = 1
'Loop through all files in the array(myFiles)
If Fnum > 0 Then
For Fnum = LBound(MyFiles) To UBound(MyFiles)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(MyPath & MyFiles(Fnum))
On Error GoTo 0
If Not mybook Is Nothing Then
On Error Resume Next
With mybook.Worksheets(1)
Set sourceRange = .Range("A1:C1")
End With
If Err.Number > 0 Then
Err.Clear
Set sourceRange = Nothing
Else
'if SourceRange use all columns then skip this file
If sourceRange.Columns.Count >= BaseWks.Columns.Count Then
Set sourceRange = Nothing
End If
End If
On Error GoTo 0
If Not sourceRange Is Nothing Then
SourceRcount = sourceRange.Rows.Count
If rnum + SourceRcount >= BaseWks.Rows.Count Then
MsgBox "Sorry there are not enough rows in the sheet"
BaseWks.Columns.AutoFit
mybook.Close savechanges:=False
GoTo ExitTheSub
Else
'Copy the file name in column A
With sourceRange
BaseWks.cells(rnum, "A"). _
Resize(.Rows.Count).Value = MyFiles(Fnum)
End With
'Set the destrange
Set destrange = BaseWks.Range("B" & rnum)
'we copy the values from the sourceRange to the destrange
With sourceRange
Set destrange = destrange. _
Resize(.Rows.Count, .Columns.Count)
End With
destrange.Value = sourceRange.Value
rnum = rnum + SourceRcount
End If
End If
mybook.Close savechanges:=False
End If
Next Fnum
BaseWks.Columns.AutoFit
End If
ExitTheSub:
'Restore ScreenUpdating, Calculation and EnableEvents
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
End Sub
See the link below for some ideas of how to get data from several Excel files/sources, consolidate into one single file/source.
http://www.rondebruin.nl/win/s3/win008.htm
Keep an open mind about this kind of stuff. There are several other ways to do essentially the same kind of thing.
The question is too broad and you can achieve your requirement in many ways.
If you consider using c# you can develop a WPF or Winforms Project.
You will need to follow these basic steps
A function to browse and pick your file like FolderBrowserDialog available in System.Windows.Forms. In case you are using WPF you have to add reference to the library
Read the excel contents. In this case you may need references to any library/nuget package like Epplus, Microsoft.Office.Interop.Excel, LinqToExcel or ExcelLibrary
Convert data to json format using Newtonsoft.Json nuget package
Upload or save data to SQL Server - Here you would need a connection string to the database and save the same in your .config file. you can use ADO, linq to sql etc for that.
Sample Code
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Excel files (*.xls)|*.csv|All files (*.*)|*.*";
if (openFileDialog.ShowDialog()== DialogResult.OK)
{
//Open file and read contents
var excelFile = new LinqToExcel.ExcelQueryFactory(path);
var query =
from row in excelFile.Worksheet("Sheet1")
let item = new
{
Column1 = row["Column1"].Cast<string>(),
Column2 = row["Column2"].Cast<int>(),
}
select item;
foreach (var item in query)
{
MyCustomClass myClass = new MyCustomClass();
myClass.Column1 = item.Column1;
myClass.Column2 = item.Column2;
//Do something
}
//convert to json
// Save to database
}
I have to write some Access VBA to export data from an Access query into a specific range of cells in an Excel document that has several worksheets.
I am having trouble finding the right way to specify the worksheet AND range.
Here is what I have so far:
docmd.TransferSpreadsheet(TransferType:=acExport, SpreadsheetType:=acSpreadsheetTypeExcel8, TableName:=qry_Main, _
FileName:="c:\test.xlsm", _
HasFieldNames:=False, _
Range:="Main!J9:J10")
The broken piece is Range:="Main!J9:J10"
What's the proper way to make this reference?
You can use CopyFromRecordset and automation:
Sub XLTrans()
''Reference: Microsoft ActiveX Data Object x.x Library
Dim rs As New ADODB.Recordset
Dim xl As Object ''Excel.Application
Dim wb As Object ''Workbook
Set xl = CreateObject("Excel.Application")
''Pick one
''1. New book
Set wb = xl.Workbooks.Add
''2. Existing book
Set wb = xl.Workbooks.Open("z:\docs\book1.xlsx")
''Connection relevant for 2007 or 2010
rs.Open "MyTableOrQuery", CurrentProject.AccessConnection
wb.Sheets("Sheet1").Cells(4, 5).CopyFromRecordset rs
xl.Visible = True
End Sub
Note that this will not include column headings, but you can add them as well, for example:
For i = 0 To rs.Fields.Count - 1
Worksheets("Sheet1").Cells(3, i + 5) = rs(i).Name
Next
http://msdn.microsoft.com/en-us/library/office/ff844793.aspx
http://msdn.microsoft.com/en-us/library/office/aa141565(v=office.10).aspx
You cannot use RANGE for exporting:
"
Range Optional Variant. A string expression that's a valid range of cells or the name of a range in the spreadsheet. This argument applies only to importing. Leave this argument blank to import the entire spreadsheet. When you export to a spreadsheet, you must leave this argument blank. If you enter a range, the export will fail.
"
I am working on a system that has been in use since the 90's. Written in VB6, it was originally setup to utilize an Access Database and the JET driver.
Now, since we have clients running up against the 2GB file size limit on Access DBs, we are looking into converting everything over to mySQL.
Unfortunately, everything in the system that was written prior to about 5 years ago is using this type of logic:
Dim rst As New ADODB.Recordset
rst.ActiveConnection = cnn
rst.Open "table"
rst.Index = "index"
rst.Seek Array("field1", "field2"), adSeekFirstEQ
rst!field1 = "something new"
rst.Update
The newer code is using SQL commands like SELECT, UPDATE, etc.
So, what we're hoping to do is to phase in the new mySQL DBs for our clients - get them the DB setup but using all the old code.
The problem is that I can't use Index when using the SQL db... everything else seems to work fine except for that.
I get the error: #3251: Current provider does not support the necessary interface for Index functionality.
Is there something I'm missing? Is there another way to so a Seek when using SQL so that I can sort by my Index? Or will I have to go in and change the entire system and remove all the Seek logic - which is used THOUSANDS of times? This is particularly an issue for all of our Reports where we might have a Table with an Index where Col 1 is sorted ASC, Col 2 is sorted DESC, Col 3 is ASC again and I need to find the first 5 records where Col 1 = X. How else would you do it?
Since, as you posted, the DB doesn't support Seek or Index, you're kind of out of luck as far as that is concerned.
However, if you really must use seek /index I'd suggest importing the result of the SQL query into a local .mdb file and then using that to make the recordset work like the rest of the code expects.
This is slightly evil from a performance point of view, and honestly it may be better to replace all the seeks and index calls in the long run anyways, but at least it'll save you time coding.
For creating the local db you can do:
Function dimdbs(Temptable as String)
Dim tdfNew As TableDef
Dim prpLoop As Property
Dim strDbfullpath As String
Dim dbsn As Database
Dim idx As Index
Dim autofld As Field
'PARAMETERS: DBFULLPATH: FileName/Path of database to create
strDbfullpath = VBA.Environ$("TMP") & "\mydb.mdb"
If Dir(strDbfullpath) <> "" Then
Set dbsn = DBEngine.Workspaces(0).OpenDatabase(strDbfullpath)
Else
Set dbsn = DBEngine.CreateDatabase(strDbfullpath, dbLangGeneral)
End If
Set tdfNew = dbsn.CreateTableDef(Temptable)
With tdfNew
' Create fields and append them to the new TableDef
' object. This must be done before appending the
' TableDef object to the TableDefs collection of the
' database.
Set autofld = .CreateField("autonum", dbLong)
autofld.Attributes = dbAutoIncrField
.Fields.Append autofld
.Fields.Append .CreateField("foo", dbText, 3)
.Fields.Append .CreateField("bar", dbLong)
.Fields.Append .CreateField("foobar", dbText, 30)
.Fields("foobar").AllowZeroLength = True
Set idx = .CreateIndex("PrimaryKey")
idx.Fields.Append .CreateField("autonum")
idx.Unique = True
idx.Primary = True
.Indexes.Append idx
Debug.Print "Properties of new TableDef object " & _
"before appending to collection:"
' Enumerate Properties collection of new TableDef
' object.
For Each prpLoop In .Properties
On Error Resume Next
If prpLoop <> "" Then Debug.Print " " & _
prpLoop.Name & " = " & prpLoop
On Error GoTo 0
Next prpLoop
' Append the new TableDef object to the Northwind
' database.
If ObjectExists("Table", Temptable & "CompletedCourses", "Userdb") Then
dbsn.Execute "Delete * FROM " & Temptable & "CompletedCourses"
Else
dbsn.TableDefs.Append tdfNew
End If
Debug.Print "Properties of new TableDef object " & _
"after appending to collection:"
' Enumerate Properties collection of new TableDef
' object.
For Each prpLoop In .Properties
On Error Resume Next
If prpLoop <> "" Then Debug.Print " " & _
prpLoop.Name & " = " & prpLoop
On Error GoTo 0
Next prpLoop
End With
Set idx = Nothing
Set autofld = Nothing
End Function
to find and delete it later you can use the following:
Function DeleteAllTempTables(strTempString As String, Optional tmpdbname As String = "\mydb.mdb", Optional strpath As String = "%TMP%")
Dim dbs2 As Database
Dim t As dao.TableDef, I As Integer
Dim strDbfullpath
If strpath = "%TMP%" Then
strpath = VBA.Environ$("TMP")
End If
strDbfullpath = strpath & tmpdbname
If Dir(strDbfullpath) <> "" Then
Set dbs2 = DBEngine.Workspaces(0).OpenDatabase(strDbfullpath)
Else
Exit Function
End If
strTempString = strTempString & "*"
For I = dbs2.TableDefs.Count - 1 To 0 Step -1
Set t = dbs2.TableDefs(I)
If t.Name Like strTempString Then
dbs2.TableDefs.Delete t.Name
End If
Next I
dbs2.Close
End Function
To import from SQL to that DB you'll have to get the recordset and add each record in using a for loop (unless it's a fixed ODBC connection, i think you can import directly but I don't have example code)
Dim formrst As New ADODB.recordset
Set mysqlconn = New ADODB.Connection
Dim dbsRst As recordset
Dim dbs As Database
'opens the ADODB connection to my database
Call openConnect(mysqlconn)
'calls the above function to create the temp database
'Temptable is defined as a form-level variable so it can be unique to this form
'and other forms/reports don't delete it
Call dimdbs(Temptable)
Me.RecordSource = "SELECT * FROM [" & Temptable & "] IN '" & VBA.Environ$("TMP") & "\mydb.mdb'"
Set dbs = DBEngine.Workspaces(0).OpenDatabase(VBA.Environ$("TMP") & "\mydb.mdb")
Set dbsRst = dbs.OpenRecordset(Temptable)
Set formrst.ActiveConnection = mysqlconn
Call Selectquery(formrst, strSQL & strwhere & SQLorderby, adLockReadOnly, adOpenForwardOnly)
With formrst
Do Until .EOF
dbsRst.AddNew
dbsRst!foo = !foo
dbsRst!bar = !bar
dbsRst!foobar = !foobar
dbsRst.Update
.MoveNext
Loop
.Close
End With
dbsRst.Close
Set dbsRst = Nothing
dbs.Close
Set formrst = Nothing
You'll have to re-import the data on save or on form close at the end, but at least that will only need one SQL statement, or you can do it directly with the ODBC connection.
This is by far less than optimal but at least you can couch all this code inside one or two extra function calls and it won't disturb the original logic.
I have to give huge credit to Allen Browne, I pulled this code from all over the place but most my code probably comes from or has been inspired by his site (http://allenbrowne.com/)
Who wants to use VB6? Nevertheless...
When you do not specify Provider, you can't use Index property. As far as i know only OleDb for MS Jet supports *Seek* method and *Index* property.
Please read this:
Seek method - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675109%28v=vs.85%29.aspx
Index property - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675255%28v=vs.85%29.aspx
ConnectionString property - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675810%28v=vs.85%29.aspx
Provider property - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675096%28v=vs.85%29.aspx
For further information, please see: http://msdn.microsoft.com/en-us/library/windows/desktop/ms681510%28v=vs.85%29.aspx
[EDIT]
After your comments...
I would strongly recommend to download and install Visual Studio Express Edition and use VB.NET instead VB6. Than install ADO.NET MySQL Connector and re-write application, using the newest technology rather than torturing yourself with ADODB objects, etc.
Examples:
Connecting to MySQL databases using VB.NET
[/EDIT]
i need procedure in VBA to import data into access from csv excel file without some records,, as header and footer. Example,,, i have table in csv file, which contains some
sentence which not belong table date
A1 this is some sentence title.......
A2 title
A3.......
A7 DATA DATA DATA DATA DATA
A8 rows DATA DATA DATA DATA DATA
......
....
A256 DATA DATA DATA DATA
A257 this is some sentence
My Acess shoud contain only rows between A7 to A256. Does anyone knows procedure or whatever in VBA who solves my problems ?
thanks a lot
Edit
The easiest way to do it is to link the CSV-file into the Access database as a table. Then you can work on this table as if it was an ordinary access table, for instance by creating an appropriate query based on this table that returns exactly what you want.
You can link the table either manually or with VBA like this
DoCmd.TransferText TransferType:=acLinkDelim, TableName:="tblImport", _
FileName:="C:\MyData.csv", HasFieldNames:=true
Update
Dim db As DAO.Database
' Re-link the CSV Table
Set db = CurrentDb
On Error Resume Next: db.TableDefs.Delete "tblImport": On Error GoTo 0
db.TableDefs.Refresh
DoCmd.TransferText TransferType:=acLinkDelim, TableName:="tblImport", _
FileName:="C:\MyData.csv", HasFieldNames:=true
db.TableDefs.Refresh
' Perform the import
db.Execute "INSERT INTO someTable SELECT col1, col2, ... FROM tblImport " _
& "WHERE NOT F1 IN ('A1', 'A2', 'A3')"
db.Close: Set db = Nothing
Your file seems quite small (297 lines) so you can read and write them quite quickly. You refer to Excel CSV, which does not exists, and you show space delimited data in your example. Furthermore, Access is limited to 255 columns, and a CSV is not, so there is no guarantee this will work
Sub StripHeaderAndFooter()
Dim fs As Object ''FileSystemObject
Dim tsIn As Object, tsOut As Object ''TextStream
Dim sFileIn As String, sFileOut As String
Dim aryFile As Variant
sFileIn = "z:\docs\FileName.csv"
sFileOut = "z:\docs\FileOut.csv"
Set fs = CreateObject("Scripting.FileSystemObject")
Set tsIn = fs.OpenTextFile(sFileIn, 1) ''ForReading
sTmp = tsIn.ReadAll
Set tsOut = fs.CreateTextFile(sFileOut, True) ''Overwrite
aryFile = Split(sTmp, vbCrLf)
''Start at line 3 and end at last line -1
For i = 3 To UBound(aryFile) - 1
tsOut.WriteLine aryFile(i)
Next
tsOut.Close
DoCmd.TransferText acImportDelim, , "NewCSV", sFileOut, False
End Sub
Edit re various comments
It is possible to import a text file manually into MS Access and this will allow you to choose you own cell delimiters and text delimiters. You need to choose External data from the menu, select your file and step through the wizard.
About importing and linking data and database objects -- Applies to: Microsoft Office Access 2003
Introduction to importing and exporting data -- Applies to: Microsoft Access 2010
Once you get the import working using the wizards, you can save an import specification and use it for you next DoCmd.TransferText as outlined by #Olivier Jacot-Descombes. This will allow you to have non-standard delimiters such as semi colon and single-quoted text.
I am trying to write a VBA script which imports all of the Excel files in a folder into a table in Access 2003, first checking if they have been imported or not. That part is fine. The issue I run into is clearing out some of the formulas that don't get used on the spreadsheet which causes difficulty when Access tries to import the range. when running the code as-is, I get an error "User-defined type not defined".
I am using late binding since I am developing for a site that uses multiple versions of Office and therfore can't reference the same library using early binding. The problem code is below:
Private Sub Command2_Click()
'Declare Variables
Dim xlApp As Object
Dim xlBook As Object
Dim LSQL As String
Dim SkippedCounter As Integer
Dim ImportedCounter As Integer
Dim BUN As Long
Dim SubmitDate As Date
Dim LSQL2 As String
Dim LSQL3 As String
'Start counters for final notice
SkippedCounter = 0
ImportedCounter = 0
Dim myDir As String, fn As String
'Set directory for importing files
myDir = "U:\Five Star\Operations\restore\Surveys\My InnerView - 2010\Action plans\Action plans - input for DB\"
'Function for selecting files in folder
fn = Dir(myDir & "*.xls")
'Determine if there are files in side the folder
If fn = "" Then
MsgBox "Folder is Empty!"
Else
'Begin cycling through files in the folder
Do While fn <> ""
'Create new Excel Object
Set xlApp = CreateObject("Excel.Application")
'Make it appear on the screen while importing
xlApp.Visible = True
'Open the workbook at hand
Set xlBook = xlApp.Workbooks.Open(myDir & fn)
'Check to see if it has been imported already
If xlBook.Sheets("Action plan form").Range("A1").Value = "Imported" Then
'If it has been imported, add 1 to the counter, close the file and close the instance of Excel
SkippedCounter = SkippedCounter + 1
xlBook.Close
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
Else
'Otherwise, unprotect the worksheet
xlBook.UnProtect Password:="2010"
Dim c As Range
'Unhide worksheet needed and clean it up
xlBook.Sheets("Action plan DB data").Visible = True
xlBook.Sheets("Action plan DB data").Range("B10:O10").ClearFormats
xlBook.Sheets("Action plan DB data").Range("N11:N84").ClearFormats
For Each c In xlBook.Sheets("Action plan DB data").Range("DB_import")
If c.Value = "" Or c.Value = 0 Then c.Clear
Next c
...
The rest of the code should run fine, it jsut has an issue with the declaration of "range" and looping through it. Thanks for your help!
Remove As Range from Dim c As Range and that will make c into an object. That way when it gets late-bound to a range you won't have any issues.