I need to automate some data extraction from a Microsoft Access DB. The DB is provided to me by a third party, and so I do not have control over what is in the DB when it is received. I need to use Powershell to automate extraction of data from the DB.
Is there any way to use powershell to create a query in the accessDB? This is, essentially, the essence of the code I am looking for:
$l_dbPath = "C:\Path\To\dataBase.accdb"
$l_accessApp = new-object -com access.application
$l_accessApp.OpenCurrentDatabase($l_dbPath)
$l_query = "SELECT SomeTable.SomeField From SomeTable;"
$l_queryName = "Export_Query"
$l_accessApp.CurrentDB().CreateQueryDef($l_queryName, $l_query)
$l_outputFile = "C:\temp\output.csv"
$e_acExportDelim = 2 #$l_accessApp.Enumerations.AcTextTransferType.acExportDelim #arg. this does not seem to exist...
$e_HasFieldNamesYes=-1
$l_exportSpec = ""
$l_accessApp.DoCmd.TransferText($e_acExportDelim,$l_exportSpec,$l_queryName,$l_outputFile,$e_HasFieldNamesYes)
$l_accessApp.CloseCurrentDatabase()
However, the line $l_accessApp.CurrentDB.CreateQueryDef($l_queryName, $l_query)
fails, because $l_accessApp.CurrentDB()
returns null, not the current DB. I can find no way to access CreateQueryDef
from Powershell.
I have looked at Programmatically Build Access Query, Create a query dynamically through code in MSAccess 2003 [VBA], Use Powershell to create access 2007 Queries?, and other posts, but found nothing that works.
Thanks for any help.
EDIT:
It turns out that the code as I had it above does, in fact, work! The issue all along was simply that I did not have a machine on which I had both DAO and Access installed. After testing the separate components (using DAO, and using Access) on different machines, and getting IT support to give me a machine with DAO and Access both actually installed, the above code does in fact work. (With MS Access installed and loaded, but DAO not installed, $l_accessApp.CurrentDB()
returns $null
. With DAO installed, it returns a DBEngine object, as expected.)
Creating a querydef:
$dbe =new-Object -comobject DAO.DBEngine.120
$path="c:\path\to\db.mdb"
$db = $dbe.opendatabase($path)
$l_query = "select table1.* from table1"
$l_queryName="testquery"
$l_outputFile="z:\test.csv"
$db.CreateQueryDef($l_queryName, $l_query)
$db.closedatabase
$l_outputFile = "z:\test.csv"
$e_acExportDelim = 2
$e_HasFieldNamesYes=-1
$l_exportSpec = ""
$l_accessApp = new-object -com access.application
$l_accessApp.OpenCurrentDatabase($path)
$l_accessApp.DoCmd.TransferText($e_acExportDelim,$l_exportSpec,$l_queryName,$l_outputFile,$e_HasFieldNamesYes)
$l_accessApp.CloseCurrentDatabase()
$l_accessApp.CloseCurrentDatabase()
You may want to give something like this a try. You're extracting information into a CSV without creating a query definition in MS Access.
$OpenStatic = 3
$LockOptimistic = 3
$path = "C:\Path\To\dataBase.accdb"
$connection = New-Object -ComObject ADODB.Connection
$RecordSet = New-Object -ComObject ADODB.Recordset
$connection.Open("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=$Path" )
$Query = "SELECT SomeTable.SomeField From SomeTable;"
$RecordSet.Open($Query, $Connection, $OpenStatic, $LockOptimistic)
$RecordSet | Out-File z:\output.csv
A different approach. Are you married to the idea of actually creating a query def? My understanding is you're after the results...is this not the case?
#db path
$DBPath = "c:\path\to\db.mdb"
#SQL statement to run
$SQL = "select table1.* from table"
#Output file location
$Output = "z:\test.csv"
#Connection
$Con= New-Object -TypeName System.Data.OleDb.OleDbConnection
#Connection string
$con.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source= $path"
#create command and fill dataset
$ConCommand= $Con.CreateCommand()
$ConCommand.CommandText = $SQL
$OAdapt = New-Object -TypeName System.Data.OleDb.OleDbDataAdapter $ConCommand
$DS = New-Object -TypeName System.Data.DataSet
$OAdapt.Fill($DS)
#Export
$DS.Tables[0] | export-csv $Output -NoTypeInformation
$Con.Close()
ExportSpecification is what that needs to be played here in order to get some desired output. This specification has to be created from within Microsoft Access using a wizard.
Using exact paths and specification names, later you have to run above script to get the desired output.
Can you use DAO?
$OpenStatic = 3
$LockOptimistic = 3
$dbe =new-Object -comobject DAO.DBEngine.120
$db = $dbe.opendatabase("C:\Path\To\dataBase.accdb")
$Query = "SELECT SomeTable.SomeField From SomeTable;"
$rs=$db.openrecordset($query)
$rs| Out-File z:\output.csv