As to me, ADODB is something new for me that I am eager to learn. Here's a code that I tried my best but needs your ideas to make it appear more professional and more efficient. The problem in the code is that the data is grabbed from sheets in reverse order and not in the order of sheets. To make it clear, I have Sample.xlsx workbook with two sheets Sheet1 and New and the code is supposed to loop through t he sheets then search for specific header then to get the data from such a column. All this with the ADO approach. the code grabs the data from New sheet first then from Sheet1 .. While the order of the sheets is Sheet1 then New >> another point, how can I close the recordset properly. I mean is using .Close is enough or I have to set it to Nothing Set rs=Nothing.
Sub ImportFromClosedWorkbook()
Dim e, ws As Worksheet, cn As ADODB.Connection, rs As ADODB.Recordset, rsHeaders As ADODB.Recordset, b As Boolean, sFile As String, shName As String, strSQL As String, iCol As Long
sFile = ThisWorkbook.Path & "\Sample.xlsx"
'shName = "Sheet1"
Dim rsData As ADODB.Recordset
Set cn = New ADODB.Connection
cn.Open ConnectionString:="Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & sFile & "';" & "Extended Properties=""Excel 12.0;HDR=YES;IMEX=1;"";"
'--------
Set ws = ThisWorkbook.ActiveSheet
Set rs = cn.OpenSchema(20)
Do While Not rs.EOF
sName = rs.Fields("Table_Name")
If Right(sName, 14) <> "FilterDatabase" Then
sName = Left(sName, Len(sName) - 1)
'Debug.Print sName
b = False
strSQL = "SELECT * FROM [" & sName & "$]"
Set rsHeaders = New ADODB.Recordset
rsHeaders.Open Source:=strSQL, ActiveConnection:=cn, Options:=1
For iCol = 0 To rsHeaders.Fields.Count - 1
'Debug.Print rsHeaders.Fields(iCol).Name
For Each e In Array("Ref No", "Reference", "Number")
If e = rsHeaders.Fields(iCol).Name Then
b = True: Exit For
End If
Next e
If b Then Exit For
Next iCol
If b Then
'Debug.Print e
strSQL = "SELECT [" & e & "] FROM [" & sName & "$]"
Set rsData = New ADODB.Recordset
Set rsData = cn.Execute(strSQL)
ws.Range("A" & ws.Cells(Rows.Count, 1).End(xlUp).Row + 1).CopyFromRecordset rsData
rsData.Close
'here I am stuck of how to get the data from the found column
End If
'rs.Close
End If
rs.MoveNext
Loop
'rs.Close
'------------------
' strSQL = "SELECT * FROM [" & shName & "$]"
' Set rs = New ADODB.Recordset
' Set rs = cn.Execute(strSQL)
' Range("A1").CopyFromRecordset rs
rs.Close: Set rs = Nothing
cn.Close: Set cn = Nothing
End Sub
the code grabs the data from New sheet first then from Sheet1 .. While the order of the sheets is Sheet1 then New
The tab order is an Excel feature. The Sheet names are extracted in alphabetical order when you use ADODB. This is the reason why you get New sheet first and then Sheet1.
Note: If the sheet names start with number or have spaces then they are given a priority first. Few examples
Example 1
Sheets names: 1, Sheet1, 1Sheet4, She et3, Sheet5
Returned as
'1$'
'1Sheet4$'
'She et3$'
Sheet1$
Sheet5$
Example 2
Sheets names: Sheet2, Sheet5, She et3, Sheet1, Sheet4
Returned as
'She et3$'
Sheet1$
Sheet2$
Sheet4$
Sheet5$
Example 3
Sheets names: 1, Sheet1, 2, Sheet2, 3, Sheet3
Returned as
'1$'
'2$'
'3$'
Sheet1$
Sheet2$
Sheet3$
Alternative to ADODB
If you want to extract the names of the sheets in the tab order then you can use DAO as shown by Andrew Poulsom in THIS link. Posting the code here in case the link dies...
Sub GetSecondSheetName()
' Requires a reference to Microsoft DAO x.x Object Library
' Adjust to suit
Const FName As String = "P:\Temp\MrExcel\Temp\SheetNames.xls"
Dim WB As DAO.Database
Dim strSheetName As String
Set WB = OpenDatabase(FName, False, True, "Excel 8.0;")
' TableDefs is zero based
strSheetName = WB.TableDefs(1).Name
MsgBox strSheetName
WB.Close
End Sub
Close is enough or I have to set it to Nothing Set rs=Nothing.
No you do not have to set it to nothing. VBA cleans it automatically when it exits the prodecure. But yes it is a good practice to flush the toilet.
Interesting Read:
You may want to read the post by #GSerg in the below link...
When should an Excel VBA variable be killed or set to Nothing?
For it to work with XLSX, use this (Requires a reference to Microsoft Office XX.XX Access database engine Object Library)
Option Explicit
'~~> Change this to the relevant file name
Const FName As String = "C:\Users\routs\Desktop\Delete Me later\TEXT.XLSX"
Sub Sample()
'Requires a reference to Microsoft Office XX.XX Access database engine Object Library
Dim db As DAO.Database
Set db = OpenDatabase(FName, False, False, "Excel 12.0")
Dim i As Long
For i = 0 To db.TableDefs.Count - 1
Debug.Print db.TableDefs(i).Name
Next i
db.Close
End Sub
In Action
#Siddharth Rout you have inspired me how to search for such new topic for me and I could use such a code to list all the worksheets in the order of tab using DAO but with late binding ( I am curious to know how to use early binding as I tried but with no success)
Sub Get_Worksheets_Using_DAO()
Dim con As Object, db As Object, sName As String, i As Long
Set con = CreateObject("DAO.DBEngine.120")
sName = ThisWorkbook.Path & "\Sample.xlsx"
Set db = con.OpenDatabase(sName, False, True, "Excel 12.0 XMl;")
For i = 0 To db.TableDefs.Count - 1
Debug.Print db.TableDefs(i).Name
Next i
db.Close: Set db = Nothing: Set con = Nothing
End Sub
Related
I am trying to figure out how to get data that I am importing into Excel from an Access table to import into a specific sheet (Either a sheet just called Sheet 2 or Access Data). I have the following code to get the data and to format it the way I want after import, but I can't get it to import into a specific sheet. Can I get assistance? Here's what I have:
Update to the code with resolution:
Sub getAccessData()
Dim DBFullName As String
Dim Connect As String, Source As String
Dim Connection As ADODB.Connection
Dim Recordset As ADODB.Recordset
Dim Col As Integer
Dim lngLastColumn As Long
Dim lngLastRow As Long
Dim OXLSheet As Worksheet
Set OXLSheet = Worksheets("WorksheetName")
Worksheets("WorksheetName").Cells.Clear
'Datebase path info
DBFullName = "C:\Users\myname\Desktop\Database Backups\database.accdb"
'Open the connection for the database
Set Connection = New ADODB.Connection
Connect = "Provider=Microsoft.ACE.OLEDB.12.0;"
Connect = Connect & "Data Source=" & DBFullName & ";"
Connection.Open ConnectionString:=Connect
'Create RecordSet
Set Recordset = New ADODB.Recordset
With Recordset
'Data Filter
Source = "SELECT * FROM tblRetirements WHERE [AllowEnteredInPayroll] Is Null AND ApplicationCancelled = 'No'"
.Open Source:=Source, ActiveConnection:=Connection
'Write field Names
For Col = 0 To Recordset.Fields.Count - 1
Worksheets("WorksheetName").Range("A5").Offset(0, Col).Value = Recordset.Fields(Col).Name
Next
'Write Recordset
Worksheets("WorksheetName").Range("A5").Offset(1, 0).CopyFromRecordset Recordset
End With
ActiveSheet.Columns.AutoFit
Set Recordset = Nothing
Connection.Close
Set Connection = Nothing
With OXLSheet
lngLastColumn = .Cells(5, .Columns.Count).End(xlToLeft).Column
lngLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
.ListObjects.Add(xlSrcRange, .Range(.Cells(5, 1), .Cells(lngLastRow, lngLastColumn)), , xlYes).Name = "Table1"
ActiveSheet.ListObjects("Table1").TableStyle = "TableStyleMedium16"
End With
End Sub
Thank you.
There is a typo, SELECT*FROM, should be SELECT * FROM.
If you want to import into a specific sheet, name output, please try replace:
Range("A5").Offset(0, Col).Value = Recordset.Fields(Col).Name with Worksheets("output").Range("A5").Offset(0, Col).Value = Recordset.Fields(Col).Name
Range("A5").Offset(1, 0).CopyFromRecordset Recordset with Worksheets("output").Range("A5").Offset(1, 0).CopyFromRecordset Recordset
If you want to copy your data in a specific worksheet, for instance named Sheet2
' Declare a worksheet object
Dim objSheet As Worksheet
' initialize it
Set objSheet = ActiveWorkbook.Sheets("Sheet2")
'Write field Names
For Col = 0 To Recordset.Fields.Count - 1
objSheet.Range("A5").Offset(0, Col).Value = Recordset.Fields(Col).Name
Next
'Write Recordset
objSheet.Range("A5").Offset(1, 0).CopyFromRecordset Recordset
Here is generic code to import the data from specific worksheets in all EXCEL files (worksheet names are the same in all files) that are located within a single folder. All of the EXCEL files' worksheets with the same worksheet names must have the data in the same layout and format.
Sub TryThis()
Dim strPathFile As String, strFile As String, strPath As String
Dim blnHasFieldNames As Boolean
Dim intWorksheets As Integer
' Replace 3 with the number of worksheets to be imported
' from each EXCEL file
Dim strWorksheets(1 To 3) As String
' Replace 3 with the number of worksheets to be imported
' from each EXCEL file (this code assumes that each worksheet
' with the same name is being imported into a separate table
' for that specific worksheet name)
Dim strTables(1 To 3) As String
' Replace generic worksheet names with the real worksheet names;
' add / delete code lines so that there is one code line for
' each worksheet that is to be imported from each workbook file
strWorksheets(1) = "GenericWorksheetName1"
strWorksheets(2) = "GenericWorksheetName2"
strWorksheets(3) = "GenericWorksheetName3"
' Replace generic table names with the real table names;
' add / delete code lines so that there is one code line for
' each worksheet that is to be imported from each workbook file
strTables(1) = "GenericTableName1"
strTables(2) = "GenericTableName2"
strTables(3) = "GenericTableName3"
' Change this next line to True if the first row in EXCEL worksheet
' has field names
blnHasFieldNames = False
' Replace C:\Documents\ with the real path to the folder that
' contains the EXCEL files
strPath = "C:\Documents\"
' Replace 3 with the number of worksheets to be imported
' from each EXCEL file
For intWorksheets = 1 To 3
strFile = Dir(strPath & "*.xls")
Do While Len(strFile) > 0
strPathFile = strPath & strFile
DoCmd.TransferSpreadsheet acImport, _
acSpreadsheetTypeExcel9, strTables(intWorksheets), _
strPathFile, blnHasFieldNames, _
strWorksheets(intWorksheets) & "$"
strFile = Dir()
Loop
Next intWorksheets
End Sub
I'm using some VBA to import an excel file into Access.
Public Sub ImportExcelSpreadsheet(fileName As String, tableName As String)
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12, tableName, fileName, True, "A5:H5000"
End Sub
And:
Private Sub btnBrowse_Click()
Dim diag As Office.FileDialog
Dim Item As Variant
Set diag = Application.FileDialog(msoFileDialogFilePicker)
diag.AllowMultiSelect = False
diag.Title = "Please select your excel file"
diag.Filters.Clear
diag.Filters.Add "Excel files", "*.xls, *.xlsx"
If diag.Show Then
For Each Item In diag.SelectedItems
Me.txtFileName = Item
Next
End If
End Sub
The problem is as follows:
I extract an excel file from one of the applications we have running here. It's a 97-2003 .xls file.
If I do not open the file in excel first my access app will not import it, throwing a "table is in unexpected format"-error. If I open the excel file once in excel itself and close it (without altering or saving it) access will then accept the file.
I have other 97-2003 excel files exported from other applications which work fine without having to open them once...am at a loss here.
I've tried using acSpreadsheetTypeExcel8 and 9 instead. No luck.
The excel file is also not a .htm in disguise.
Does anyone here have any suggestions?
Can you export from Excel to Access using ADO???
Sub ADOFromExcelToAccess()
' exports data from the active worksheet to a table in an Access database
' this procedure must be edited before use
Dim cn As ADODB.Connection, rs As ADODB.Recordset, r As Long
' connect to the Access database
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0; " & _
"Data Source=C:\FolderName\DataBaseName.mdb;"
' open a recordset
Set rs = New ADODB.Recordset
rs.Open "TableName", cn, adOpenKeyset, adLockOptimistic, adCmdTable
' all records in a table
r = 3 ' the start row in the worksheet
Do While Len(Range("A" & r).Formula) > 0
' repeat until first empty cell in column A
With rs
.AddNew ' create a new record
' add values to each field in the record
.Fields("FieldName1") = Range("A" & r).Value
.Fields("FieldName2") = Range("B" & r).Value
.Fields("FieldNameN") = Range("C" & r).Value
' add more fields if necessary...
.Update ' stores the new record
End With
r = r + 1 ' next row
Loop
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub
Can you do the same using DAO???
Sub DAOFromExcelToAccess()
' exports data from the active worksheet to a table in an Access database
' this procedure must be edited before use
Dim db As Database, rs As Recordset, r As Long
Set db = OpenDatabase("C:\FolderName\DataBaseName.mdb")
' open the database
Set rs = db.OpenRecordset("TableName", dbOpenTable)
' get all records in a table
r = 3 ' the start row in the worksheet
Do While Len(Range("A" & r).Formula) > 0
' repeat until first empty cell in column A
With rs
.AddNew ' create a new record
' add values to each field in the record
.Fields("FieldName1") = Range("A" & r).Value
.Fields("FieldName2") = Range("B" & r).Value
.Fields("FieldNameN") = Range("C" & r).Value
' add more fields if necessary...
.Update ' stores the new record
End With
r = r + 1 ' next row
Loop
rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
End Sub
Can you import to Access form a closed Workbook???
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
Finally...can you browse to an Excel file and import data from that file???
Dim strPathFile As String
Dim strTable As String, strBrowseMsg As String
Dim strFilter As String, strInitialDirectory As String
Dim blnHasFieldNames As Boolean
' Change this next line to True if the first row in EXCEL worksheet
' has field names
blnHasFieldNames = False
strBrowseMsg = "Select the EXCEL file:"
' Change C:\MyFolder\ to the path for the folder where the Browse
' window is to start (the initial directory). If you want to start in
' ACCESS' default folder, delete C:\MyFolder\ from the code line,
' leaving an empty string as the value being set as the initial
' directory
strInitialDirectory = "C:\MyFolder\"
strFilter = ahtAddFilterItem(strFilter, "Excel Files (*.xls)", "*.xls")
strPathFile = ahtCommonFileOpenSave(InitialDir:=strInitialDirectory, _
Filter:=strFilter, OpenFile:=False, _
DialogTitle:=strBrowseMsg, _
Flags:=ahtOFN_HIDEREADONLY)
If strPathFile = "" Then
MsgBox "No file was selected.", vbOK, "No Selection"
Exit Sub
End If
' Replace tablename with the real name of the table into which
' the data are to be imported
strTable = "tablename"
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel9, _
strTable, strPathFile, blnHasFieldNames
' Uncomment out the next code step if you want to delete the
' EXCEL file after it's been imported
' Kill strPathFile
Try these examples and post back with your findings.
I am creating an ADODB connection to a Sybase database, executing an SQL statement into a recordset, and then using the CopyFromRecordset method to paste the contents of the recordset to a range. This has been working fine but I recently moved PC's at work and now one of the columns is returning nothing.
When I run the same SQL in SQuirreL the column is not blank.
If I pause the VBA and try to look at one of the values in the column / field in question (ie ?rst.fields(1).value in the immediate Window) I get the following error message:
Run-time error '-2147467259 (80004005)': Unspecified error.
In the Squirrel results Metadata tab the column in question is described as:
ColumnIndex 2
getColumnName CommentText
getColumnTypeName text
getPrecision 2147483647
getScale 0
isNullable 0
getTableName xxxxxxx
getSchemaName
getCatalogName
getColumnClassName java.sql.Clob
getColumnDisplaySize 2147483647
getColumnLabel CommentText
getColumnType 2005
isAutoIncrement FALSE
isCaseSensitive FALSE
isCurrency FALSE
isDefinitelyWritable FALSE
isReadOnly FALSE
isSearchable FALSE
isSigned FALSE
isWritable TRUE
The code in question is below, but, as stated the code does not seem to be the problem as it has worked previously - any ideas?
Sub ImportComments()
Dim wsData As Worksheet
Dim rng As Range
Dim cn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim x As Long
Dim rngSQL As Range
Dim cell As Range
Dim sSQL As String
Dim sProvider As String
Dim sDS As String
Dim sDataSource As String
Dim sUser As String
Dim sCatalog As String
Dim sPassword As String
Dim rngDS As Range
Dim rngThisDS As Range
Dim sConnect As String
Dim sInstance As String
Dim fSuccess As Boolean
Dim sError As String
On Error GoTo ProcExit
'delete previous comments if they exist
If SheetExists("Comments_Data_Import", ThisWorkbook) = True Then
Application.DisplayAlerts = False
ThisWorkbook.Sheets("Comments_Data_Import").Delete
Application.DisplayAlerts = True
End If
'create comments sheet
Set wsData = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets("EWI_Data_Import"))
wsData.Name = "Comments_Data_Import"
'build sql string
Set rngSQL = Range(ThisWorkbook.Sheets("SQL").Range("A2"), _
ThisWorkbook.Sheets("SQL").Range("A2").End(xlDown))
For Each cell In rngSQL
sSQL = sSQL & cell.Value & " "
Next cell
'define login components
Set rngDS = ThisWorkbook.Worksheets("Login").Range("rngInstance").CurrentRegion
Set rngDS = rngDS.Offset(1, 0).Resize(rngDS.Rows.Count - 1)
sProvider = "Provider=ASEOLEDB.1;"
sUser = "User ID=" & ThisWorkbook.Worksheets("Login").Range("rngUsername").Value & ";"
sPassword = "Password=" & ThisWorkbook.Worksheets("Login").Range("rngPassword").Value
'try to log in to each instance exiting when succesful
Set cn = New ADODB.Connection
cn.CommandTimeout = 600
'turn off error hadling to allow for connection errors On Error Resume Next
For Each rngThisDS In rngDS.Rows
'complete connect string
Err = 0
sInstance = rngThisDS.Cells(1, 1)
sDS = "Data Source=" & rngThisDS.Cells(1, 2) & ";"
sCatalog = "Initial Catalog=" & rngThisDS.Cells(1, 3) & ";"
sConnect = sProvider & sDS & sUser & sCatalog & sPassword
'attempt to open
cn.Open sConnect
'If successful Then
If Err = 0 Then
'flag success
fSuccess = True
'execute SQL
On Error GoTo ProcError
Set rst = cn.Execute(sSQL)
'copy data into comments sheet
wsData.Range("A2").CopyFromRecordset rst
'Put in the headers
Set rng = wsData.Range("A1")
For x = 1 To rst.Fields.Count
rng.Offset(0, x - 1).Value = rst.Fields(x - 1).Name
Next x
FormatComments
Exit For
End If
Next rngThisDS
If fSuccess = False Then
MsgBox ("Unable to connect to Insight")
Else
MsgBox "Connected to and exported data from " & sInstance
End If
ProcExit:
Set wsData = Nothing
Set rng = Nothing
Set cn = Nothing
Set rst = Nothing
Set rngSQL = Nothing
Set cell = Nothing
Set rngDS = Nothing
Set rngThisDS = Nothing
Exit Sub
ProcError:
MsgBox "Error: " & Err.Description
Resume ProcExit
End Sub
According to the CopyFromRecordset() MSDN:
When this method copies the recordset to the worksheet, the results
will be truncated if you do not specify a range that is large enough
to hold the contents of the recordset.
Consider specifying the range with MoveFirst command reset:
' Copy data into comments sheet
rst.MoveLast
rst.MoveFirst
wsData.Range("A2:Z500").CopyFromRecordset rst
Or entire worksheet (starting at A1, of course inserting row for column headers)
wsData.Cells.CopyFromRecordset rst
But even then, CopyFromRecordset() is sensitive to data and cursory types even memory (since you pull all data and dump at once), so consider altogether replacing the method and iterate through records for the rows. Even other languages (PHP, Python, Java, etc.) run queries this way, opening cursor and iterating through resultset.
' Put in the headers
Set rng = wsData.Range("A1")
For x = 1 To rst.Fields.Count
rng.Offset(0, x - 1).Value = rst.Fields(x - 1).Name
Next x
' Put in rows
Dim col As Integer, row As Integer
rst.MoveLast
rst.MoveFirst
Set rng = wsData.Range("A2")
row = 0
Do While Not rst.EOF
For col = 0 To rst.Fields.Count - 1
rng.Offset(row, col).Value = rst(col)
Next col
row = row + 1
rst.MoveNext
Loop
This is related to
Excel / VBA Remove duplicate rows by cross referencing 2 different sheets then deleting 1 row
I can't seem to get any VBA to work well or fast enough for a couple 100 rows.
Does Excel have a formula to remove duplicates from one sheet, by cross referencing another sheet?
Thanks for all your help.
Here is a much faster VBA solution, utilizing a dictionary object. As you can see, it loops only once through sheet A and sheet B, while your original solution has a running time proportional to "number of rows in sheet A" * "number of rows in sheet B".
Option Explicit
Sub CleanDupes()
Dim wsA As Worksheet
Dim wsB As Worksheet
Dim keyColA As String
Dim keyColB As String
Dim rngA As Range
Dim rngB As Range
Dim intRowCounterA As Integer
Dim intRowCounterB As Integer
keyColA = "A"
keyColB = "B"
intRowCounterA = 1
intRowCounterB = 1
Set wsA = Worksheets("Sheet A")
Set wsB = Worksheets("Sheet B")
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Do While Not IsEmpty(wsA.Range(keyColA & intRowCounterA).Value)
Set rngA = wsA.Range(keyColA & intRowCounterA)
If Not dict.Exists(rngA.Value) Then
dict.Add rngA.Value, 1
End If
intRowCounterA = intRowCounterA + 1
Loop
intRowCounterB = 1
Do While Not IsEmpty(wsB.Range(keyColB & intRowCounterB).Value)
Set rngB = wsB.Range(keyColB & intRowCounterB)
If dict.Exists(rngB.Value) Then
wsB.Rows(intRowCounterB).Delete
intRowCounterB = intRowCounterB - 1
End If
intRowCounterB = intRowCounterB + 1
Loop
End Sub
You can do a lot with ADO and Excel.
Dim cn As Object
Dim rs As Object
Dim wb As Workbook
Dim sSQL As String
Dim sFile As String
Dim sCon As String
Dim sXLFileToProcess As String
Dim i
sXLFileToProcess = "Book1z.xls"
sFile = Workbooks(sXLFileToProcess).FullName
''Note that if HDR=No, F1,F2 etc are used for column names,
''if HDR=Yes, the names in the first row of the range
''can be used.
''This is the Jet 4 connection string, you can get more
''here : http://www.connectionstrings.com/excel
sCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sFile _
& ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
''Late binding, so no reference is needed
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
cn.Open sCon
'' In this example, the column header for column F is F, see notes
'' above on field (column) names. It also assumes that the sheets to
'' be merged have the same column headers in the same order
'' It would be safer to list the column heards rather than use *.
sSQL = sSQL & "SELECT b.Key,b.b,b.c,b.d,b.e FROM [SheetB$] As B " _
& "LEFT JOIN [SheetA$] As A " _
& "ON B.Key=A.Key " _
& "WHERE A.Key Is Null"
rs.Open sSQL, cn, 3, 3
Set wb = Workbooks.Add
With wb.Worksheets("Sheet1")
For i = 1 To rs.Fields.Count
.Cells(1, i) = rs.Fields(i - 1).Name
Next
.Cells(2, 1).CopyFromRecordset rs
End With
''Tidy up
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
I have a workbook with multiple sheets, and have created Named Tables (NOT ranges) in the work book. For illustrative purposes, these table names are tblA, tblB, and tblC. I am unable to find a way to query these tables via ADO or ODBC. I can access named ranges, but this will not work for my needs.
Thanks!
I don't know if it can be done directly but will be interested to see if anyone comes back with a working method. The GetSchema collection of ADO only seems to pick up sheetnames and named ranges but not ListObjects which named tables are. Below is a workaround but it means opening Excel to find the header/data range of the table. It's almost pointless using ADO or similar then as you can copy the data directly but I suppose you could convert to a named range before saving as a one-off task?
Option Explicit
Sub test()
Dim WB As Workbook, WS As Worksheet, strExcelfile As String, strSheetName As String
Dim strTableName As String, objListObj As ListObject, HeaderRange As String
Dim strSQL As String, DataRange As String
strExcelfile = "C:\Users\osknows\Desktop\New folder\test.xlsm"
strSheetName = "Sheet1"
strTableName = "TableName"
Set WB = GetObject(strExcelfile) 'Filepath & Filename
Set WS = WB.Sheets(strSheetName) 'SheetName
Set objListObj = WS.ListObjects(strTableName) 'Table Name
'get range of Table
HeaderRange = objListObj.HeaderRowRange.Address
DataRange = objListObj.DataBodyRange.Address
'write data directly if required
With ThisWorkbook
With Sheet1
'.Range(HeaderRange).Value = WS.Range(HeaderRange).Value
'.Range(DataRange).Value = WS.Range(DataRange).Value
End With
End With
'or use ADODB which is a bit pointless now!
Dim cnn1 As New ADODB.Connection
Dim rst1 As New ADODB.Recordset
cnn1.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & strExcelfile & ";" & _
"Extended Properties=""Excel 12.0;HDR=No;IMEX=1"";"
strSQL = "SELECT * FROM [" & strSheetName & "$" & Replace(DataRange, "$", "") & "];"
rst1.Open strSQL, cnn1, adOpenStatic, adLockReadOnly
'tidy up
Set objListObj = Nothing
Set WS = Nothing
WB.Close
Set WB = Nothing
End Sub