Excel VBA query table properties - excel

I have an odbc query table which is currently working, but I need to define the field selected form the database by a value in cell D18.
The following code should replace the command text in the query table properties but it doesn't work.
debug says "Subscript out of range". if i debug and run ?text in the immediate window then run this resulting text line in SQL it returns the correct value, so the sql statement is right. what have i got wrong in the vba syntax
Sub Accrual()
Text = "SELECT "
Text = Text & "BALANCE.CDTLED_" & Range("D11").Value - 1 & " "
Text = Text & "FROM x3sov.SOVEX.BALANCE BALANCE "
Text = Text & "WHERE (BALANCE.ACC_0='2109') AND (BALANCE.FCY_0='S01')"
Sheets("Control").QueryTables(1).CommandText = Text
End Sub
any help much appreciated

Since Excel introduced ListObjects (called Tables in the UI), you can no longer rely on QueryTables.Count to get to all the external data connections. If you don't have any QueryTables, then the external data connection goes through a ListObject.
Sheet1.ListObjects(1).QueryTable.CommandText = Text
Note that ListObject doesn't have a QueryTables property, but a QueryTable property because there's always only one.

Related

CopyFromRecordset from Access to Excel is out of Order

Very frustrating results from:
ws.Range(myExcelTable).CopyFromRecordset rs
' myExcelTable is a named table with assigned range
The pull for rs (the recordset, is a select all, doesn't matter if it is done this way or with field names, it is the same result)
cmdSQL2 = "SELECT * FROM " & myAccessTable
rs.Open cmdSQL2, conn
For an unknown reason it copies records into excel in this order (using pID to show ordering):
3-8
0-2
9-number of records
I have tried several range methods and the result is the same.
I will "hand bomb" them here to cut out the extra work I performed in building range strings.
ws.Range("S4").CopyFromRecordset rs
ws.Range("S4:BP258").CopyFromRecordset rs
This behavior does not appear if the table you are copying from Access has only one Field (column) and the Table in Excel has a single header (column), but it is appearing for me now in this multi-field table.
I feel this is happening when the recordset is actually created somehow and not on the "paste" or assignment side (Excel).
'*************************************************************************
Problem Solved by this SO Contributor (will leave here until it is placed as an answer):
https://stackoverflow.com/users/7296893/erik-a
Using ORDER BY in the sql sommand:
cmdSQL2 = "SELECT * FROM " & myAccessTable & " ORDER BY " & primaryKey
From immediate window (removes the variables so you can see the command better for those new to such things:
SELECT * FROM County_Directory ORDER BY [pID]
'*************************************************************************

Passing string result to query then export as csv

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.

How do I construct a SELECT statement incorporating Excel cell values?

I am querying an external database with power query through Excel. What I am wanting to do is populate my where clause based off of cell values so for example my sql statement would read something like
Select *
From employees
where hiredate between Sheet1!A1 and Sheet2!A2
I tried the above syntax and it does not work, but I think it illustrates what I am wanting to achieve.
How can I pass parameters from my Excel sheet into my power query syntax?
EDIT
I tried following the blog.oraylis.de (not actual link, link is in comments), but I get the below error when I try to execute my statement
DataSource.Error ODBC:Error[4203] ERROR: column "start_p" does not exist;
I created a table named it parameters added headers & Values, and the full SQL I try to run is this:
let
startp_Param = Excel.CurrentWorkbook(){[Name="Parameter"]}[Content],
startp_Value = startp_Param {0}[Value],
endp_Param = Excel.CurrentWorkbook(){[Name="Parameter"]}[Content],
endp_Value = endp_Param {1}[Value],
Source = Odbc.Query("dsn=postgresql", "Select * FROM employees where hiredate BETWEEN startp_Value AND endp_Value")
in
Source
EDIT # 2
I altered my query to read like this
"Select *
FROM employees
where hiredate BETWEEN " & startp_Value & " AND " & endp_Value
However this now presents an error of:
"We cannot apply operator & to types Text and Number"
startp_Value and endp_Value are steps in Power Query, so you have to use & to add it to the string, like this:
Source = Odbc.Query("dsn=postgresql", "Select * FROM employees where hiredate BETWEEN " & startp_Value & " AND " & endp_Value
This doesn't handle sanitizating your SQL query, so you may want to do it to startp_Value and endp_Value (for example, by converting to a Date and then back to a Text).

Control the behaviour of #ClientType formula in Lotus

I ran into an issue with the #ClientType formula in Lotus Notes. This formula should show the client type. From the Lotus help:
Returns "Notes" if the client type is a Lotus Notes client Returns
"Web" if the client type is a Web browser
#ClientType is useful within database formulas, form formulas, buttons
in forms, and "hide-when" formulas. Do not use #ClientType in column
formulas. #ClientType always returns "None" when executed in a server
background agent.
However if I run this code in an agent or action hotspot in the client:
x = Evaluate("#ClientType")
MsgBox x(0)
The result is "Web".
And if I use the notesDocument.RenderToRTItem( notesRichTextItem ) or notesDocument.ConvertToMIME( conversionType, options ) function, the #ClientType formula is also evaluated to "Web"
This is relevant because some fields in the document form in the document library use this formula in the hide when options. When a document is rendered to rich text or to MIME, this field is not included.
Is there any way to control the behavior of this formula? My only other option is to change the hide when formula's, but I would rather leave the design of the database as is.
Even though it's working on a computed field, if your agent gets that document handle then you can get from the computed field. Whereas it will not work in column formula which is already mentioned in help document.
It seems that the solution is to convert the session's convertmime flag to true after your doc.converttomime call
Code below is run from a scheduled agent.
Test 1 returns 'Nothing'
Test 2 returns 'Web'
Test 3 returns 'Nothing'
Sub Initialize
Dim s As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim vntClientType As Variant
Set db=s.Currentdatabase
On Error GoTo ErrorHandling
vntClientType = Evaluate("#ClientType")
MessageBox " Test 1 before converttomime " & vntClientType(0)
Set doc=New NotesDocument(db)
Call doc.converttomime
vntClientType = Evaluate("#ClientType")
MessageBox " Test 2 after converttomime" & vntClientType(0)
s.convertmime=True
vntClientType = Evaluate("#ClientType")
MessageBox " Test 3 after s.convertmime= true" & vntClientType(0)
Exit Sub
ErrorHandling:
Error Err, Error & " - " & ", at line " & Erl & { in "} & GetThreadInfo( 1 ) & {"}
End Sub

Custom Mapping tool for txt or excel

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

Resources