Is there an easy way for me to turn the following, if only for a second, into real SQL?:
=IFERROR(eagle("SELECT SUM("&selectedmonth&")/1000, ("& ytdformula & ")/1000 AS YTD, sum(Budget)*"&sMonthIndex&"/12000
FROM ["&environment&"].[dbo].[SD_"&selectedyear&"_flat" & IF(selectedCurrency="USD","","_EUR") &"]
WHERE 1=1
"&IF(selectedDepartment="All",""," AND department = '"&selectedDepartment&"'")&"
"&IF(selectedproduct="All",""," AND product = '"&selectedproduct&"'")&"
"&IF(AND(getMacro=FALSE,getRatesNSU=FALSE),
IF(selecteddivision="All",""," AND division='"&selecteddivision&"'"),
IF(getMacro=TRUE," AND (division = 'Commodities' OR division = 'FX Products' OR division = 'Rate Products')"," AND (division = 'Rate Products' OR product = 'IB Non-Strategic Unit')"))&"
"&IF(exclSMG=FALSE,""," AND Division <> 'Systematic Market Making'")&"
"&IF(selectedsubdivision="All",""," AND subdivision = '"&selectedsubdivision&"'")&"
"&IF(selectedcluster="All",""," AND cluster = '"&selectedcluster&"'")&"
"&IF(selectedregion="All",""," AND region = '"&selectedregion&"'")&"
"&IF(selectedBiz="All",""," AND business_unit IN "&selectedBiz),connectionString),0)
Put the word stop in front of this line of code then paste the following into the VBA Immediate window with a question mark in front of it.
?"SELECT SUM("&selectedmonth&")/1000, ("& ytdformula & ")/1000 AS YTD, sum(Budget)*"&sMonthIndex&"/12000
FROM ["&environment&"].[dbo].[SD_"&selectedyear&"_flat" & IF(selectedCurrency="USD","","_EUR") &"]
WHERE 1=1
"&IF(selectedDepartment="All",""," AND department = '"&selectedDepartment&"'")&"
"&IF(selectedproduct="All",""," AND product = '"&selectedproduct&"'")&"
"&IF(AND(getMacro=FALSE,getRatesNSU=FALSE),
IF(selecteddivision="All",""," AND division='"&selecteddivision&"'"),
IF(getMacro=TRUE," AND (division = 'Commodities' OR division = 'FX Products' OR division = 'Rate Products')"," AND (division = 'Rate Products' OR product = 'IB Non-Strategic Unit')"))&"
"&IF(exclSMG=FALSE,""," AND Division <> 'Systematic Market Making'")&"
"&IF(selectedsubdivision="All",""," AND subdivision = '"&selectedsubdivision&"'")&"
"&IF(selectedcluster="All",""," AND cluster = '"&selectedcluster&"'")&"
"&IF(selectedregion="All",""," AND region = '"&selectedregion&"'")&"
"&IF(selectedBiz="All",""," AND business_unit IN "&selectedBiz),connectionString),0)
The Immediate window will concatenate all the variables and literals into the SQL String that it is attempting to execute.
IF there is errors in the SQL, you should be able to copy the SQL into the QBE editor to get the error message the compiler cannot reconcile.
Related
I'm using Excel and VBA to get SAP to download data from SAP through RFC using INST_EXECUTE_REPORT.
It works like a charm when I have specific input parameters. I just build up .Tables("PARA") with the screen name of the parameter and the desired value. I can even use this method for date ranges.
The challenge is when I don't know exactly the input parameters. For example, I wanted to identify all internal orders with a specific text in the description, e.g. CODE40.
Is there any way to use wildcards with INST_EXECUTE_REPORT? When the program passed into INST_EXECUTE_REPORT is executed normally as a transaction on screen, I can set the parameter to *CODE40* and SAP automatically applies a wildcard search. But I can't get that to work with VBA.
I can simulate using wildcards when accessing individual tables with BBP_RFC_READ_TABLE by using LIKE statements in the selection option, but I need a similar functionality for whole reports, not individual tables.
Can anyone help?
Best regards,
The code I'm using is as follows:
Set ObjR3_EXECUTE_REPORT = ObjR3.Add("INST_EXECUTE_REPORT")
With ObjR3_EXECUTE_REPORT
Set ObjR3_EXECUTE_REPORT_Name = .Exports("PROGRAM")
Set ObjR3_EXECUTE_REPORT_Para = .Tables("PARA")
Set ObjR3_EXECUTE_REPORT_Result = .Tables("RESULT_TAB")
Set ObjR3_EXECUTE_REPORT_Output = .Tables("OUTPUT_TAB")
End With
ObjR3_EXECUTE_REPORT_Name.Value = ReportName
'Build up the table with the fields to be selected
f = 1
For a = LBound(aParameters) To UBound(aParameters)
aParameterPair = aParameters(a)
aParameterInput = aParameterPair(UBound(aParameterPair))
sParameterName = aParameterPair(LBound(aParameterPair))
For c = LBound(aParameterInput) To UBound(aParameterInput)
sParameterInput = aParameterInput(c)
ObjR3_EXECUTE_REPORT_Para.AppendRow
ObjR3_EXECUTE_REPORT_Para(f, "PARA_NAME") = sParameterName
ObjR3_EXECUTE_REPORT_Para(f, "PARA_VALUE") = sParameterInput
Debug.Print sParameterName & " " & sParameterInput
f = f + 1
Next c
Next a
I would like to create the dropdown list with the results from my query. I'm looking for help please because I don't know how to display this results on the list.
The exemple of the list:
My query is :
'DROPDOWN LIST
Private Sub cb_gest_Change()
If Not FSD.cb_gest.MatchFound And FSD.cb_gest <> "" Then
MsgBox "Saisie impossible, le gestionnaire n'existe pas !", , "ContrĂ´le
Gestionnaire"
FSD.cb_gest = ""
Else
FSD.Cells(29, COL_DATA) = FSD.cb_gest
End If
End Sub
'DROPDOWN LIST
Sub init_combo()
Dim Resultat As ADODB.Recordset
Dim Requete As String
FSD.cb_gest.Clear
Requete = "select lb_gestion from DB_GESTIONNAIRE "
Requete = Requete + "WHERE (d_deb_valid <= TRUNC(SYSDATE) OR d_deb_valid IS
NULL) AND (d_fin_valid >= TRUNC(SYSDATE) OR d_fin_valid IS NULL)"
Requete = Requete + " ORDER BY LB_GESTION"
Set Resultat = New ADODB.Recordset
Resultat.ActiveConnection = oBase
Resultat.Source = Requete
Resultat.Open
While Not Resultat.EOF
FSD.cb_gest.AddItem Resultat!lb_gestion
Resultat.MoveNext
Wend
If FSD.Cells(29, COL_DATA).Value <> "" Then
FSD.cb_gest = FSD.Cells(29, COL_DATA).Value
Else
FSD.Cells(29, COL_DATA).Value = ""
End If
End Sub
Thank you for your help !
Consider a different, codeless approach:
Add a new sheet to the host document / workbook
Import the external data from the "Data" Ribbon tab (select "From SQL Server")
Excel creates a ListObject table backed with a QueryTable object that uses a WorkbookConnection that can be configured to automatically refresh on open, or left alone as a one-time pull.
Select the produit column in the ListObject/table; Excel highlights the entire column content and leaves the heading un-selected.
From the "Formulas" Ribbon tab, click the "Define Name" command in the "Defined Names" group.
Name the range ProductsList, verify it refers to TableName[produit] so that it automatically grows and shrinks to fit the column contents.
Change the data validation list to =ProductsList.
Hide the worksheet housing the query and table, if needed.
No code needed, and the validation list will always keep up with the query results as they are refreshed.
Side note, the query appears to be making inefficient cross-joins, and at least one of them is a where-join that can be expressed as an inner join. Are you sure the query is yielding the expected records (I'm suspecting it's yielding a ton of duplicates, depending on how many records exist in the cross-joined tables)?
SELECT prod.cd_produit AS produit
FROM db_dossier sousc, db_produit prod, db_protocole proto, db_tiers tiers, db_personne pers
WHERE sousc.cd_dossier = 'SOUSC' AND sousc.lp_etat_doss NOT IN ('ANNUL','A30','IMPAY') AND sousc.is_produit = prod.is_produit
Instinct would be to remove the tables we're not selecting or filtering anything from - if this query produces the same expected output, then assuming primary and foreign keys are defined I believe its execution plan would be more efficient:
SELECT prod.cd_produit AS produit
FROM db_dossier AS sousc
INNER JOIN db_produit AS prod ON sousc.is_produit = prod.is_produit
WHERE sousc.cd_dossier = 'SOUSC' AND sousc.lp_etat_doss NOT IN ('ANNUL','A30','IMPAY')
I've written an export (Access to Excel) function in an application that works in ranges.
The user has 4 RadioButtons: A-F, G-M, N-R and S-Z.
Let's say the user has selected rbtnAF, which will load all customers into the grid where the Customer_Code field starts with an A, B, C, D, E or F.
The code to load in the data is as follows:
Dim strFields As String = "[Customer_Addresses].[Cust_Code], [Customers].[Customer_Name], [Customer_Addresses].[Contact_Code], [Customer_Addresses].[Contact_Name], " & _
"[Customer_Addresses].[Contact_Type], [Customer_Addresses].[Add1], [Customer_Addresses].[Add2], [Customer_Addresses].[Add3], [Customer_Addresses].[Add4], " & _
"[Customer_Addresses].[Add5], [Customer_Addresses].[Postcode], [Customer_Addresses].[Country], [Customer_Addresses].[Telephone], [Customer_Addresses].[Fax], " & _
"[Customer_Addresses].[Email], [Customer_Addresses].[Mobile_Phone], [Customers].[Customer_Category], [Customers].[Average_Payment_Terms], " & _
"[Customers].[Notes], [Customers].[salesRep], [Customers].[hoEmail], [Customers].[webpage] FROM Customers " & _
"INNER JOIN Customer_Addresses ON [Customers].[Customer_Code] =[Customer_Addresses].[Cust_Code]"
If rbtnAF.Checked = True Then
sql = "SELECT " & strFields & " WHERE [Customer_Addresses].[Cust_Code] BETWEEN " & _
"'A*' AND 'F*' ORDER BY [Customer_Addresses].[Cust_Code]"
Dim da As New OleDbDataAdapter(sql, con)
Dim ds As New DataSet
Dim dt As New System.Data.DataTable
da.Fill(ds)
dt = ds.Tables(0).Copy()
ugExport.DataSource = Nothing
ugExport.DataSource = dt
This was, I thought, working fine, I was able to load the correct ranges into the grid and export them as I wanted.
However, the user has come back to me and said it's not loading all customers.
I thought this was a bit weird, so I loaded up their database and tested it for myself. In the DB, there are 4 customers who fit into the range of A-F, as you can see in this image.
However, when I then view the customer range A-F in the export list, there are only 2 customers displayed.
It's also worth noting, in the Customer List screen there is a TextBox to allow the user to search by customer code - When I type in just a single F, all 4 customers are displayed as expected.
What on Earth is going on to only display 2 of the results in the Export List, despite there being 4 records that fit the criteria?
Checking the between syntax you will find that it treats * as a literal character see here https://support.office.com/en-us/article/Between-And-Operator-a435878d-63f7-4825-8c31-999432ae8223
You can use
Like "[A-F]*"
Instead though.
I'm using Matlab R2014b (that's why I cannot use strings, but only char vectors). Working inside a class, I have to take data from a table variable, format it following my needs, and then insert it into a GUI table (an instance of uitable, to be exact):
function UpdateTable(this)
siz = size(mydata);
tab = cell(siz);
tab(:,1) = num2cell(this.Data.ID);
tab(:,2) = cellstr(datestr(this.Data.Date,'dd/mm/yyyy'));
tab(:,3) = arrayfun(#(x){MyClass.TypeDef1{x,1}},this.Data.Type1);
tab(:,4) = arrayfun(#(x){MyClass.TypeDef2{x,1}},this.Data.Type2);
tab(:,5) = arrayfun(#(x){MyClass.FormatNumber(x)},this.Data.Value);
this.UITable.Data = tab;
end
Where:
properties (Access = private, Constant)
TypeDef1 = {
'A1' 'Name A1';
'B1' 'Name B1';
'C1' 'Name C1';
'D1' 'Name D1';
...
}
TypeDef2 = {
'A2' 'Name A2';
'B2' 'Name B2';
'C2' 'Name C2';
'D2' 'Name D2';
...
}
end
methods (Access = private, Static)
function str = FormatNumber(num)
persistent df;
if (isempty(df))
dfs = java.text.DecimalFormatSymbols();
dfs.setDecimalSeparator(',');
dfs.setGroupingSeparator('.');
df = java.text.DecimalFormat();
df.setDecimalFormatSymbols(dfs);
df.setMaximumFractionDigits(2);
df.setMinimumFractionDigits(2);
end
str = char(df.format(num));
end
end
Everything is working fine. Now I would like to right justify the strings to be inserted in columns 1 and 5, to improve the table readability. I found the Matlab function that suits my needs, strjust. Reading the documentation, I saw that it can be used with cell arrays of char vectors, so I modified part of my UpdateTable code as follows:
tab(:,1) = cellstr(num2str(this.Data.ID));
tab(:,5) = strjust(arrayfun(#(x){MyClass.FormatNumber(x)},this.Data.Value));
TThe second one produces no changes (strings are still not justified). Should the strings already contain enough whitespace to be all the same length?
Ok, I solved the problem by myself using the following code:
function UpdateTable(this)
siz = size(this.Data);
los = arrayfun(#(x){MyClass.FormatNumber(x)},this.Data.Value);
los_lens = cellfun(#(x)numel(x),los);
pad = cellfun(#blanks,num2cell(max(los_lens) - los_lens),'UniformOutput',false);
tab = cell(siz);
tab(:,1) = cellstr(num2str(this.Data.ID));
tab(:,2) = cellstr(datestr(this.Data.Date,'dd/mm/yyyy'));
tab(:,3) = arrayfun(#(x){MyClass.TypeDef1{x,1}},this.Data.Type1);
tab(:,4) = arrayfun(#(x){MyClass.TypeDef2{x,1}},this.Data.Type2);
tab(:,5) = cellstr(strcat(pad,los));
this.UITable.Data = tab;
end
It's probably not the most elegant solution, but it works. Starting from Matlab 2016, the padding can be performed using the built-in pad function.
The following code helps to import a sales line to an invoice:
Dim LineItems(dtItem.Rows.Count) As taSopLineIvcInsert_ItemsTaSopLineIvcInsert
Dim salesLine As New taSopLineIvcInsert_ItemsTaSopLineIvcInsert
'Create Invoice Sales lines
For Each dr In dtItem.Rows
With salesLine
.CUSTNMBR = dr.Item("acctno")
.SOPNUMBE = invoiceNumber
.SOPTYPE = 3
.DOCID = "STD INV"
.QUANTITY = dr.Item("Qty")
.ITEMNMBR = dr.Item("Item")
.ITEMDESC = dr.Item("Memo")
.UNITPRCE = dr.Item("SalesPrice")
.XTNDPRCE = dr.Item("Credit")
.TAXAMNT = 0
.UOFM = "Each"
.SALSTERR = "GENERAL"
.ReqShipDate = dtHdr.Rows(0).Item("InvoiceDate").ToString()
.FUFILDAT = dr.Item("Date1").ToString()
.ACTLSHIP = dr.Item("Date1").ToString()
'.NONINVEN = 0
.DOCDATE = dtHdr.Rows(0).Item("InvoiceDate").ToString()
.SLPRSNID = "C1"
End With
LineItems(rowCtr) = salesLine
rowCtr = rowCtr + 1
Next
The fields for SLPRSNID & SALSTERR are just ignored. The invoice itself is being created with all the line items. ANY ideas from anyone with experience using this API are appreciated!
Since we are not integrating SOP commissions data, importing SLPRSNID & SALSTERR on line items using code like above is not supported. However, eConnect does expose pre and post stored procedures to customize business logic. The following was added in taSopHdrIvcInsertPost to implement the import:
/** Custom Business Logic */
if ((#I_vSLPRSNID <> '') and (#I_vSALSTERR <> ''))
begin
update SOP10200
set SLPRSNID = #I_vSLPRSNID, SALSTERR = #I_vSALSTERR
where SOPNUMBE = #I_vSOPNUMBE and SOPTYPE = #I_vSOPTYPE
end
/** Custom Business Logic */
NOTE: with this implementation, the specific SLPRSNID & SALSTERR will have to be provided to the line items, it will not automatically post from header data, or any customer setup data in GP - your integration has to pass the values in.