I have an excel dokument (tab delimitted). Every time before i can insert the excel in my program, i need to map the clients column names to the ones in my app.
So before i begin developing a mapping tool - it would be better if such already existed. But, i don't know i didn't find it.
This tool would actually read an excel or txt file, allow me to name all the names of the new columns on the right and drag and drop (for example).
Maybe this tool has an xml or something where i can define my custom columns, and then it would show op on the right side.
I hope you know what i mean and that someone also had the need for this.
Thanks
info update
I wanted to mention a few things as an update to my question if it's not to late: I have about 50 headers/columns (example: First Name, Middle Name, Street1, Street2,..). So what i always need do every time a client gives me his excel file (contacts backup) is manually copy data for each of his column to the one on my side. And the problem is, every client has different column names, and also some of the columns of the client can go to multiple columns on my side.
So i think, if i can't find a solution, i would make a c++/qt app, which takes an excell and lets me to assign (dragdrop,etc..) every column of his side to on or more columns of my side.
I haven't done any vb programming, so if you can be a bit more detailed about how to aproach the solution i vb that would be great.
Firs part of answer: You can achieve it with a simple vbscript. Copy this code in a vbs extension text file and double click.
Dim oCN As Connection
Dim fs As Scripting.FileSystemObject
Set oCN = New Connection
Set fs = New Scripting.FileSystemObject
sCSVFileName = "C:\Temp\Test1.csv"
sSourceSql = "SELECT field1 as f1, field2 as f2, ... FROM " &
fs.GetFileName(sCSVFileName )
sDestinationTable = "yourAppTable"
With oCN
.Provider = "Microsoft.Jet.OLEDB.4.0"
.Properties("Extended Properties").Value =
"TEXT;HDR=YES;FMT=TabDelimited;MAXSCANROWS=0"
.Open fs.GetFile(sCSVFileName).ParentFolder
End With
sSql = "INSERT INTO [ODBC;DRIVER={SQL Server};Server=" &
ServerName & ";Database=" & DBName & _
IIf(IntegratedSecurity, ";Trusted_Connection=Yes;", _
";UID=" & UID & ";PWD=" & PWD & ";") & _
"]." & sDestinationTable & " " & sSourceSql
oCN.Execute sSql, , adExecuteNoRecords
More info at microsoft social forums
Also, you can parametrize mapping (source and destination tables and mapping fields) with a external xml file.
Second part of answer: You ask if somebody else have this needed and if this is a good idea. Well, this is a very good proposal. And for this reason they are some solutions with this functionality.
First of all, this kind of technology is named ETL. Extract - Transform - Load.
Each database has its own tool
SQL Server Import and Export Wizard
Oracle data pump and loader
etc.
Also exists specific technologies:
SSIS from microsoft.
IBM WebSphere DataStage
etc.
All this tools have mapping columns capabilities.
i use a generic mapping mechanism for that, configured by a couple arrays where you put the names used in your app (aDsNames) with these in your source, the csv file in your case (aDbNames)
I walk the fields in the source, check if the getDbName(name) is in aDsNames and if so write the value in the insertstring to the database.
You can do this both ways, usually my app requests a field to the databasemodule on the server, this module translates to the databasename and does the select.
Hope this is helpfull..
Cheers
select case store
case "store1Midoc"
aDbNames = array("id" , "beheerder", "datumlijst", "rnr13" , "datvan", "dattot", "opmerking", "status" , "waarde", "kode" , "type")
aDsNames = array("id" , "persnr ", "datum ", "rnr13" , "datvan", "dattot", "opmerking", "status" , "waarde", "kode" , "type")
aTypes = array("number", "string", "date" , "string", "date" , "date" , "string" , "number", "number", "string", "string")
case .....
end select
Function getDbName(dsName)
Dim a
getDbName = "undefined"
If instr(join(aDsNames,","),dsName) Then
For a = 0 to UBound(aDbNames)
If aDsNames(a) = dsName Then
getDbName = aDbNames(a)
End If
Next
End If
End Function
Related
I have a list box that I'm trying to populate in an application to contain Excel tab names or Access tables. It's created by a simple schema grab:
dtSheet = OpenCon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, New Object() {Nothing, Nothing, Nothing, "TABLE"})
It then gets put into a simple list (of String):
For Each Row In dtSheet.Rows
ListOfSheets.Add(Row("TABLE_NAME").ToString())
Next
This works fine if I open up an Access database, the names of the tables are listed nicely. However, when I use it for Excel, I get symbols such as $ and quotes "'". I'd like to trim this off to just have the tab names but so far I haven't been able to find anything to help my issue specifically.
My suspicion is that the answer is in the {Nothing...."TABLE"} object. I'm a little light on how filters like this work and I was having issues wrapping my head around it after reading the .NET documentation.
Another idea would be to do some post string alteration trimming but I'd like to see if there was an easier way to get the simple string name that I want from the start.
Any help would be appreciated.
Based on the discussion from jmcihinney, I built a slightly better code.
dtSheet = OpenCon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, New Object() {Nothing, Nothing, Nothing, "TABLE"})
dtSheet.Columns.Add("Table_Text", Type.GetType("System.String"))
For i As Integer = dtSheet.Rows.Count - 1 To 0 Step -1
If Microsoft.VisualBasic.Strings.Right(dtSheet.Rows(i)("TABLE_NAME"), 1) <> "$" Then
dtSheet.Rows.RemoveAt(i)
Else
dtSheet.Rows(i)("TABLE_Text") = Replace(dtSheet.Rows(i)("TABLE_NAME"), "$", "")
End If
Next
I essentially add a column to the datatable that is built from the list pull. To remove anything that isn't a table (e.g. named ranges, Sheet views) I check the Table_Name column for the suffix of "$". Note I go backwards to keep from messing with any indexing.
Then in the Else statement I put a "Replace" to make the table_text a "$"less version of Table_Name
That way I can then build my listbox like this:
Me.lbTableList.DataSource = dtsheet
Me.lbTableList.DisplayMember = "TABLE_Text"
Me.lbTableList.ValueMember = "TABLE_NAME"
This makes my table look nice regardless if I loaded an Access database or Excel file. This also allows me to just pass the TABLE_NAME to the connection command and not worry whether there is a "$" in the name or not:
DBCmd.CommandText = "SELECT * FROM [" & strTable & "]"
Good Afternoon,
I have an access query that contains a list of all my customers lets call that CUS
I have another query that has a list of ORDERS
I would like to write some VBS that cycles through the customer list and exports a csv file containing all orders that belong to that customer.
The vba would then move on to the next customer on the list and perform the same action.
Any help would be great.
Snippet of code below
almost there cant get the WHERE condition working it keeps displaying a popup for me to populate however the same string is feeding the msgbox fine here is a snippet below tht is within the loop
strcustcode = rs!OCUSTCODE
ordercount = rs!orders
TIMEFILE = Format$(Time, "HHMM")
MsgBox ([strcustcode] & " has " & [ordercount] & " orders")
StrSQL = "Select * From [24-ND_Cus] where [24-ND_Cus].[OCUSTCODE] = strcustcode "
Set qd = db.CreateQueryDef("tmpExport", StrSQL)
DoCmd.TransferText acExportDelim, , "tmpExport", "c:file.csv" db.QueryDefs.Delete "tmpExport" –
Don't use [ ] around VBA variables. Don't use parens for the MsgBox when you just want to give user a message. The parens make it a function that requires a response by user to set a variable.
MsgBox strcustcode & " has " & ordercount & " orders"
Concatenate the variable into the SQL statement. If OCUSTCODE is a text type field, use apostrophe delimiters for the parameter.
StrSQL = "Select * From [24-ND_Cus] Where [OCUSTCODE] = '" & strcustcode & "'"
I don't advise code that routinely modifies design and changing a query SQL statement is changing design. If the only change is filter criteria and a dynamic parameterized query won't work, I suggest a 'temp' table - table is permanent, data is temporary. Delete and write records to the table and export the table.
If I have created a PowerQuery function that imports XML from a folder, how in the same excel file do I reuse the query when there are new files in the folder to only include data from those new files and append the data to the current table?
If you start a Power Query using From File / From Folder and browse to your folder, you will see each file represented as a row in a table, with columns such as Date modified. You can filter that list using Date/Time filters on Date modified or by something more complicated if necessary (post your specific requirements and I'll try to steer you in the right direction).
Once you have filtered the query to just the "new files", you can pass the [Content] column into your Function.
Finally Append a new query based on the saved Excel Table output from your pre-existing query together with the "new files" query above to get your combined output. The new query would be set to Load To / Only Create Connection.
you can watch a folder for file changes with a simple vba script that uses WMI to poll the directory contents every n seconds.
Something similar to this ...
Sub WatchDirectory(dir as string, every as integer)
Set wmisvc = GetObject("winmgmts:\\.\root\cimv2")
let query = "SELECT * FROM __InstanceOperationEvent " _
& "WITHIN " & every _
& " WHERE Targetinstance ISA 'CIM_DirectoryContainsFile' and " _
& "TargetInstance.GroupComponent='Win32_Directory.Name=" _
& Chr(34) & dir & Chr(34) & "'"
Set events = wmisvc.ExecNotificationQuery(query)
Do While True
Set event = events.NextEvent()
if event.Class = "__InstanceCreationEvent" then
....
end if
Loop
For more info on wmi see https://sites.google.com/site/beyondexcel/project-updates/exposingsystemsecretswithvbaandwmiapi
For more details on file watching with WMI, see https://blogs.technet.microsoft.com/heyscriptingguy/2005/04/04/how-can-i-monitor-for-different-types-of-events-with-just-one-script/
I have an Excel Spreadsheet that calculates a risk (of perioperative mortality after aneurysm repair) based on various test results.
The user inputs the test results into the spreadsheet (into cells) and then out comes a set of figures (about 6 results) for the various models that predict mortality. The spreadsheet acts as a complex function to produce the results one patient at a time.
I also have a (separate) access database holding data on multiple patients - including all the data on test results that go into the spreadsheet. At the moment I have to manually input this data into the spreadsheet, get the results out and then manually enter them onto the database.
Is there a way of doing this automatically. Ie can I export data1, data2, data3... from Access into the spreadsheet to the cells where the data needs to be input and then get the results (result1, result2, result3...) from the cells where the results are displayed ported back into access.
Ideally this could be done live.
I suppose I could try to program the functionality of the spreadheet into a complex function in access, but if I'm honest, I am not really sure how the algorithm in the spreadsheet works. It was designed by anaesthetists who are much cleverer than me....
Hope this makes sense. Any help much appreciated.
Chris Hammond
It's possible to automate Excel from Access.
Const cstrFile As String = "C:\SomeFolder\foo.xls"
Dim xlApp As Object
Dim xlWrkBk As Object
Dim xlWrkSt As Object
Set xlApp = CreateObject("Excel.Application")
xlApp.Workbooks.Open cstrFile, ReadOnly:=True
Set xlWrkBk = xlApp.Workbooks(1)
Set xlWrkSt = xlWrkBk.Worksheets(1)
With xlWrkSt
.Range("A1") = 2
.Range("A2") = 19
Debug.Print .Range("A3")
End With
xlWrkBk.Close SaveChanges:=False
However, that seems like it would be cumbersome to repeat for each row of an Access table and I'm uncertain whether doing that live is reasonable.
I would try to adapt the Excel calculations to Access VBA functions and use those custom functions in an Access query. But I don't know how big of a task that would be. I suggest you shouldn't be scared off the the anaesthetists' cleverness; that doesn't mean they actually know much more about VBA than you. At least look to see whether you can tackle it.
To push the data back to Access, you can insert data from within the Excel VBA as follows:
dim val as variant
dim db as DAO.Database
val=thisworkbook.range("a1").value
set db=OpenDatabase("c:\myAccessDB.accdb")
db.execute "insert into patientData (someField) values (" & val & ")",dbFailOnError
db.Close
You'll need to add a reference to the Microsoft Office Access Database Engine Object Library.
Not sure to perfectly understand what you want, but if you just want to export the results of a query to a spreadsheet, you could use the following:
Private Sub ExportAccessDataToExcel()
Dim SqlString As String
SqlString = "CREATE TABLE testMeasurements (TestName TEXT, Status TEXT)"
DoCmd.RunSQL (SqlString)
SqlString = "INSERT INTO testMeasurements VALUES('Average Power','PASS')"
DoCmd.RunSQL (SqlString)
SqlString = "INSERT INTO testMeasurements VALUES('Power Vs Time','FAIL')"
DoCmd.RunSQL (SqlString)
SqlString = "SELECT testMeasurements.TestName, testMeasurements.Status INTO exportToExcel "
SqlString = SqlString & "FROM testMeasurements "
SqlString = SqlString & "WHERE (((testMeasurements.TestName)='Average Power'));"
DoCmd.RunSQL (SqlString)
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel7, "exportToExcel", "C:\TestMeasurements.xls", True, "A1:G12"
End Sub
Source: http://www.ehow.com/how_7326712_save-access-query-excel-vba.html
This could be done either directly from the database or from Excel (you would need to open the database with Excel VBA to do so, but most of the Office Suite products interact well with each other).
If you want to push the data of your spreadsheet into an Access database, that's different. You just have to open the database and loop through INSERT query. Here is a quick example, you just need to add the loop:
Dim db as DAO.Database
Set db = OpenDatabase(myDataBase.mdb)
Call db.Execute("INSERT INTO myTable (Field1, Field2) VALUES('Value1', 'Value2')")
I got stuck in the problem beneath, because I don´t use Access or Excel much and I have some basic programming language. So here's the deal:
I just made a fairly simple database in MS Access (2007) with a nice query to retrieve data, depending on which parameters you pass. In Excel (2007), I have this big 'template' which basically has parameters for the query. These parameters change per column & per row!
Perhaps superfluously, e.g.
column A contains paramA (10 different options)
column B contains paramB (8 different options)
column C contains paramC (2 different options)
What I'd like to do is to fill this template with dynamic data from Access, minding the continously changing parameters.
e.g.
column D contains Query (ParamA, ParamB, ParamC)
Best way to go I think is to make a (inline?) function that retrieves results from the query, also passing the parameters depending on the relative cell position. And this function is then copied as a normal inline excel function (like: SUM()).
I just don't know how to call /execute an MS Access query from inside an Excel Macro function.
Could someone help me with it? Thank you very much in advance!
A few notes.
Dim cn As Object
Dim rs As Object
''See: http://www.connectionstrings.com/access
strFile = "C:\Docs\AccessDB.mdb"
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strFile _
& ";User Id=admin;Password=;"
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
cn.Open strCon
strSQL = "SELECT SomeField, OtherField FROM SomeTable " _
& "WHERE SomeText='" & Range("A1") & "'"
rs.Open strSQL, cn
s = rs.GetString
MsgBox s
'' Or
Sheets("Sheet2").Cells(2, 1).CopyFromRecordset rs
To add to Remou's answer also see
Modules: Sample Excel Automation - cell by cell which is slow and
Modules: Transferring Records to Excel with Automation
Late binding means you can safely remove the reference and only have an error when the app executes lines of code in question. Rather than erroring out while starting up the app and not allowing the users in the app at all. Or when hitting a mid, left or trim function call.
This also is very useful when you don't know version of the external application will reside on the target system. Or if your organization is in the middle of moving from one version to another.
For more information including additional text and some detailed links see the "Late Binding in Microsoft Access" page