Visual Fox Pro Word Automation - vba

LOCAL oWord, oDocument, oRange, Lc_start, Lc_expr, Lc_ris, Ln_count, Lc_val
DIMENSION Lc_funct[1]
Lc_expr = ""
Ln_count = 1
oWord = CREATEOBJECT("Word.Application")
oWord.Visible = .T.
cFile = GETFILE()
oDoc = oWord.Documents.Add(m.cFile)
oRange = oWord.ActiveDocument.Range()
nWordCount = oRange.Words.Count
oRange.Collapse(1)
FOR nWord = 1 TO m.nWordCount-1
oRange.Expand(2)
cWord = oRange.Text
DO CASE
CASE m.cWord = "<|<"
Lc_start = .T.
Lc_Expr = ""
CASE m.cWord = ">|>"
Lc_start = .F.
Lc_funct[Ln_count] = Lc_Expr
Ln_count = Ln_count + 1
DIMENSION Lc_funct[Ln_count]
CASE m.Lc_start
Lc_expr = Lc_expr + m.cWord
OTHERWISE
*don't do anything
ENDCASE
oRange.Collapse(0)
ENDFOR
FOR i = 1 TO Ln_count-1
oRange = oWord.ActiveDocument.Range()
oRange.Find.Text = Lc_funct[i]
oRange.Find.Replacement.Text = EVALUATE(Lc_funct[i])
lFound = oRange.Find.Execute( , , , , , , , , , , 2 )
ENDFOR
FOR i = 1 TO Ln_count-1
oRange = oWord.ActiveDocument.Range()
oRange.Find.Text = "<|<"
oRange.Find.Replacement.Text = ""
lFound = oRange.Find.Execute( , , , , , , , , , , 2 )
ENDFOR
FOR i = 1 TO Ln_count-1
oRange = oWord.ActiveDocument.Range()
oRange.Find.Text = ">|>"
oRange.Find.Replacement.Text = ""
lFound = oRange.Find.Execute( , , , , , , , , , , 2 )
ENDFOR
MESSAGEBOX("DONE")
Hello everyone. I wrote this code to automate Word from Visual Fox Pro. I put between the escapes "<|<" and ">|>" some VFP code(like take some values from tables and so on). At the press of a button, the code scans all the document and, when find these escapes, evaluates the istructions between. The last two FORs eliminate the escape strings.
The code works, but I ask. There is a better way to do what I look for?
Also, if I have a table, there is a way to decide BEFORE the automation which columns I want to pass inside the Word document?

Related

Filter only get one condition

I have a validation in WHERE clause like:
...
AND (#BDOnly = 0
OR [DT].[Abbreviation] = #IsBDChecked)
AND (#CDOnly = 0
OR [DT].[Abbreviation] = #IsCDChecked)
AND (#PPOOnly = 0
OR [DT].[Abbreviation] = #IsPPOChecked)
AND (#FBOMOnly = 0
OR [DT].[Abbreviation] = #IsFBOMChecked)
AND (#APOnly = 0
OR [DT].[Abbreviation] = #IsAPChecked)
AND (#COOnly = 0
OR [DT].[Abbreviation] = #IsCOChecked)
So each AND clause check if boolean is bit value is 0 or 1, if it's 0 just do any but if it's 1 it do a filter. My problem is
if I'm sending two with value 1, I mean
#BDOnly = 1 and #CDOnly = 1 it only filter one of them instead get two filters I mean:
[DT].[Abbreviation] = #IsBDChecked
and
[DT].[Abbreviation] = #IsCDChecked
What am I doing wrong? Regards
I'm going to take a guess here because there's not enough data. If you want to return a row where Abbreviation matched #IsBDChecked only when #BDOnly is set, and also another row where Abbreviation matches #IsCDChecked when #CDOnly is set, try this:
(#BDOnly = 1
AND [DT].[Abbreviation] = #IsBDChecked)
OR (#CDOnly = 1
AND [DT].[Abbreviation] = #IsCDChecked)
OR (#PPOOnly = 1
AND [DT].[Abbreviation] = #IsPPOChecked)
OR (#FBOMOnly = 1
AND [DT].[Abbreviation] = #IsFBOMChecked)
OR (#APOnly = 1
AND [DT].[Abbreviation] = #IsAPChecked)
OR (#COOnly = 1
AND [DT].[Abbreviation] = #IsCOChecked)
Small representative case:
DECLARE #ADOnly BIT = 0
, #BDOnly BIT = 1
, #CDOnly BIT = 1
, #IsADChecked NVARCHAR(100) = 'A'
, #IsCDChecked NVARCHAR(100) = 'C'
, #IsBDChecked NVARCHAR(100) = 'B'
;WITH myTable AS
(
SELECT * FROM (VALUES ('A'), ('B'), ('C')) X(Abbreviation)
)
SELECT *
FROM myTable
WHERE (#ADOnly = 1 AND Abbreviation = #IsADChecked)
OR (#BDOnly = 1 AND Abbreviation = #IsBDChecked)
OR (#CDOnly = 1 AND Abbreviation = #IsCDChecked)
Yields:
Abbreviation
------------
B
C

Datatables combine data from different columns into single row

Refer to the below image, how to merge all chapter into one single rows of different page number?
e.g.
Page 1 has 3 rows as there are 3 data at columns of chp 8,9,10
Page 2 has 5 rows as there are 5 data at columns of chp 8,9,1,11,12
So
how to have a single row of each page number and the all data placed at their own chp?
Basic SQL as below:
SELECT `mc_ee_page_id` as Page,
IF ( mc_ee_chp_id = 1, ( CASE
WHEN (is_marked = 0 and mk_no_mark = 1 ) THEN "Y"
WHEN (is_marked = 1 and mk_no_mark = -1) THEN "N"
WHEN (is_marked = 1 and mk_no_mark = 1 ) THEN "O" ELSE "X"
END ) , "" ) AS chp_1 ,
IF ( mc_ee_chp_id = 2, ( CASE
WHEN (is_marked = 0 and mk_no_mark = 1 ) THEN "Y"
WHEN (is_marked = 1 and mk_no_mark = -1) THEN "N"
WHEN (is_marked = 1 and mk_no_mark = 1 ) THEN "O" ELSE "X"
END ) , "" ) AS chp_2 ,
IF ( mc_ee_chp_id = 3, ( CASE
WHEN (is_marked = 0 and mk_no_mark = 1 ) THEN "Y"
WHEN (is_marked = 1 and mk_no_mark = -1) THEN "N"
WHEN (is_marked = 1 and mk_no_mark = 1 ) THEN "O" ELSE "X"
END ) , "" ) AS chp_3 ,
:
:
IF ( mc_ee_chp_id = 12, ( CASE
WHEN (is_marked = 0 and mk_no_mark = 1 ) THEN "Y"
WHEN (is_marked = 1 and mk_no_mark = -1) THEN "N"
WHEN (is_marked = 1 and mk_no_mark = 1 ) THEN "O" ELSE "X"
END ) , "" ) AS chp_12
FROM `maxcare_mc_ee_hw`
WHERE `stud_id` = '3312' AND `mc_ee_level_id` = '1'
GROUP BY mc_ee_chp_id, mc_ee_page_id
ORDER BY mc_ee_page_id asc
LIMIT 500
One way would be to GROUP the results of your SQL by making it the subquery of an outer query...
SELECT Page, MAX(chp_1) AS chp_1, MAX(chp_2) AS chp_2, MAX(chp_3) AS chp_3, MAX(chp_4) AS chp_4, MAX(chp_5) AS chp_5, MAX(chp_6) AS chp_6, MAX(chp_7) AS chp_7, MAX(chp_8) AS chp_8, MAX(chp_9) AS chp_9, MAX(chp_10) AS chp_10, MAX(chp_11) AS chp_11, MAX(chp_12) AS chp_12
FROM
(
-- *** paste your SQL in here ***
) AS indivdual_rows
GROUP BY Page
It assumes a page cannot have more than one non-blank value for the same chapter. If that is not the case, then it will only show the MAX alphabetical value.
Click here to go to SQL Fiddle to see it in action.

Converting Access DB macro into PowerBI M Language

I am in the process of converting an Access DB into a Power BI report. The Access Db has a macro that is run from a form using parameters, I have the same parameters in Power BI.
My current Power BI query is set up like this:
let
PDL=PDLedger,
PUL=PULedger,
Period=YTDMonth,
Yr=Year,
Source = Sql.Database("server", "database",
[Query="SELECT GBAID
, GBMCU
, GBOBJ
, [GBAN01]/100 AS P1
, [GBAN02]/100 AS P2
, [GBAN03]/100 AS P3
, [GBAN04]/100 AS P4
, [GBAN05]/100 AS P5
, [GBAN06]/100 AS P6
, [GBAN07]/100 AS P7
, [GBAN08]/100 AS P8
, [GBAN09]/100 AS P9
, [GBAN10]/100 AS P10
, [GBAN11]/100 AS P11
, [GBAN12]/100 AS P12
, case when GBLT = 'B2'
or GBLT = 'BU'
or GBLT = 'BA'
then 'B2' else GBLT end as GBLT
, GBFY
, GBCO
, GBSBLT
, GBSBL
FROM TableName
WHERE (((GBOBJ) Between '2000' And '8000')
AND ((GBLT)='B2'
Or (GBLT)='BA'
Or (GBLT)='AA'
Or (GBLT)='GP'
Or (GBLT)='" &PDL& "')
AND ((GBFY)='" &Yr& "'))
OR (((GBOBJ) Between '1000' And '1550')
AND ((GBLT)='BU'
Or (GBLT)='AU'
Or (GBLT)='" &PUL& "')
AND ((GBFY)='" &Yr& "')
AND ((GBSBLT)='S'
Or (GBSBLT)='P'))
ORDER BY GBOBJ",
CommandTimeout=#duration(0, 0, 10, 0), HierarchicalNavigation=true, MultiSubnetFailover=true])
in
Source
However, in the Access DB macro, there are these update scripts:
--REPORTS_040_ClearActual_TEMP
UPDATE Tbl_FCAST_TEMP
SET Tbl_FCAST_TEMP.P1 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=1,[P1],0) --period_2 = 2
, Tbl_FCAST_TEMP.P2 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=2,[P2],0) --period_2 = 2
, Tbl_FCAST_TEMP.P3 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=3,[P3],0) --period_2 = 2
, Tbl_FCAST_TEMP.P4 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=4,[P4],0) --period_2 = 2
, Tbl_FCAST_TEMP.P5 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=5,[P5],0) --period_2 = 2
, Tbl_FCAST_TEMP.P6 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=6,[P6],0) --period_2 = 2
, Tbl_FCAST_TEMP.P7 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=7,[P7],0) --period_2 = 2
, Tbl_FCAST_TEMP.P8 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=8,[P8],0) --period_2 = 2
, Tbl_FCAST_TEMP.P9 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=9,[P9],0) --period_2 = 2
, Tbl_FCAST_TEMP.P10 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=10,[P10],0) --period_2 = 2
, Tbl_FCAST_TEMP.P11 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=11,[P11],0) --period_2 = 2
, Tbl_FCAST_TEMP.P12 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=12,[P12],0) --period_2 = 2
WHERE (((Tbl_FCAST_TEMP.GBLT)='AA'
Or (Tbl_FCAST_TEMP.GBLT)='GP'
Or (Tbl_FCAST_TEMP.GBLT)='AU')
AND ((Tbl_FCAST_TEMP.GBFY)=[Forms]![Frm_Menu]![YEAR_2])); --17
--REPORTS_042_ClearFcast_TEMP
UPDATE Tbl_FCAST_TEMP
SET Tbl_FCAST_TEMP.P1 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=1,0,[P1])
, Tbl_FCAST_TEMP.P2 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=2,0,[P2])
, Tbl_FCAST_TEMP.P3 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=3,0,[P3])
, Tbl_FCAST_TEMP.P4 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=4,0,[P4])
, Tbl_FCAST_TEMP.P5 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=5,0,[P5])
, Tbl_FCAST_TEMP.P6 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=6,0,[P6])
, Tbl_FCAST_TEMP.P7 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=7,0,[P7])
, Tbl_FCAST_TEMP.P8 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=8,0,[P8])
, Tbl_FCAST_TEMP.P9 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=9,0,[P9])
, Tbl_FCAST_TEMP.P10 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=10,0,[P10])
, Tbl_FCAST_TEMP.P11 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=11,0,[P11])
, Tbl_FCAST_TEMP.P12 = IIf(([Forms]![Frm_Menu]![PERIOD_2]-1)>=12,0,[P12])
WHERE (((Tbl_FCAST_TEMP.GBLT)<>"AA"
And (Tbl_FCAST_TEMP.GBLT)<>"GP"
And (Tbl_FCAST_TEMP.GBLT)<>"B2"
And (Tbl_FCAST_TEMP.GBLT)<>"AU")
AND ((Tbl_FCAST_TEMP.GBFY)=[Forms]![Frm_Menu]![YEAR_2]));
The [Forms]![Frm_Menu]![YEAR_2] field is equivalent to the Yr=Year Parameter in the Power BI report, and the [Forms]![Frm_Menu]![PERIOD_2] is the same as the Period=YTDMonth parameter.
Is there a simple clean way to add these update scripts to the Power BI query?
EDIT:
I would like to update the fields P1 - P12 using M Language, in the same way as the Access DB macro update statements do.
I can think of two approaches to this.
1. Modify the query statement where you define your P columns.
, (CASE WHEN " & Yr & " >= 1 THEN [GBAN01]/100 ELSE 0 END) AS P1
, (CASE WHEN " & Yr & " >= 2 THEN [GBAN01]/100 ELSE 0 END) AS P2
[...]
, (CASE WHEN " & Yr & " >= 11 THEN [GBAN11]/100 ELSE 0 END) AS P11
, (CASE WHEN " & Yr & " >= 12 THEN [GBAN12]/100 ELSE 0 END) AS P12
2. If it needs to be done in M language, you can create custom columns with similar logic.
#"Custom 1" = Table.AddColumn(Source, "C1", each if Yr >= 1 then [P1] else 0),
#"Custom 2" = Table.AddColumn(#"Custom 1", "C2", each if Yr >= 2 then [P2] else 0),
[...]
#"Custom 11" = Table.AddColumn(#"Custom 10", "C11", each if Yr >= 11 then [P11] else 0),
#"Custom 12" = Table.AddColumn(#"Custom 11", "C12", each if Yr >= 12 then [P12] else 0),
Once those are created you can delete the original P columns and rename the C columns.
#"Removed Columns" = Table.RemoveColumns(#"Custom 12",{"P1", "P2", [...], "P11", "P12"}),
#"Renamed Columns" = Table.RenameColumns(#"Removed Columns",{{"C1", "P1"},{"C2", "P2"},[...],{"C11", "P11"},{"C12", "P12"}})

Crystal Reports v14 not finding all null values

Alright, I've run into this before and have gotten everything to work correctly in the past. I have an SQL code that was created that now needs to be turned into a crystal report. The SQL shows 956 lines, but Crystal is only showing 886.
Here is the SQL code:
SELECT
I4240,
I4201,
I4202,
I4203,
I4204,
I4206,
I4213,
I4214,
I4225,
I4208,
I4299
FROM
MT.INVENTORY
WHERE
(
I4202 IN ('UNKNONWN','VERIFY MFR','OTHER','VARIOUS','TBD','NA','N/A') OR
(
I4203 IN ('UNKNONWN','VERIFY MODEL NUMBER','OTHER','VARIOUS','TBD','NA','N/A','MISCELLANEOUS')
OR I4203 IS NULL
OR LENGTH(I4203)=0
) OR
(
I4204 IN ('UNKNOWN DESCRIPTION','VERIFY DESCRIPTION','OTHER','VARIOUS','TBD','NONE - NO STD USED','NA','N/A','MISCELLANEOUS')
OR I4204 IS NULL
OR LENGTH(I4204)=0
)
) AND
I4240 NOT IN ('MT','STD','NESD')
ORDER BY I4240,I4202,I4203,I4204
and the record selection formula from CR:
(
{Inventory.I4240} <> 'mt' and
{Inventory.I4240} <> 'std' and
{Inventory.I4240} <> 'nesd'
)
AND
(
(
{Inventory.I4202} = 'UNKNONWN' OR
{Inventory.I4202} = 'VERIFY MFR' OR
{Inventory.I4202} = 'OTHER' OR
{Inventory.I4202} = 'VARIOUS' OR
{Inventory.I4202} = 'TBD' OR
{Inventory.I4202} = 'NA' OR
{Inventory.I4202} = 'N/A'
)
OR
(
{Inventory.I4203} = 'UNKNONWN' OR
{Inventory.I4203} = 'VERIFY MODEL NUMBER' OR
{Inventory.I4203} = 'OTHER' OR
{Inventory.I4203} = 'VARIOUS' OR
{Inventory.I4203} = 'TBD' OR
{Inventory.I4203} = 'NA' OR
{Inventory.I4203} = 'N/A' OR
{Inventory.I4203} = 'MISCELLANEOUS' OR
ISNULL({Inventory.I4203}) OR
LENGTH(trim({Inventory.I4203})) < 1 OR
INSTR(trim({Inventory.I4203}), "") = 0 OR
TRIM({Inventory.I4203}) = ""
)
OR
(
{Inventory.I4204} = 'UNKNOWN DESCRIPTION' OR
{Inventory.I4204} = 'VERIFY DESCRIPTION' OR
{Inventory.I4204} = 'OTHER' OR
{Inventory.I4204} = 'VARIOUS' OR
{Inventory.I4204} = 'TBD' OR
{Inventory.I4204} = 'NONE - NO STD USED' OR
{Inventory.I4204} = 'NA' OR
{Inventory.I4204} = 'N/A' OR
{Inventory.I4204} = 'MISCELLANEOUS' OR
ISNULL({Inventory.I4204}) OR
LENGTH(trim({Inventory.I4204})) < 1 OR
INSTR({Inventory.I4204}, "") = 0 OR
TRIM({Inventory.I4204}) = ""
)
)
Any help would be appreciated.
In Crystal, if a particular field can be null then you need to check for that condition as the very first thing you do with it, otherwise the entire formula will error out and nothing will be evaluated.
So in your case, fields I4203 and I4204 need the isnull() check moved to the top of their respective sections at the very least. If I4240 and I4202 can be null, then you should handle those conditions as well.
Also, you have a couple references to the word "UNKNONWN"; is that a typo?
The issue was that the report options were set to use null as default, but for some reason in the record selection formula it was set to exception. Once that was set to the default setting it worked without any issues and the counts were correct.

SELECT FROM depending on a parameter in SQL

I want to obtain from a parameter, #Display the value 0, 1 or 2. When #Display = 0, I want to display all the items for which ec.IsEquipmentRelated is true. When #Display = 0, I want to display all the items for which ec.IsEquipmentRelated is false and when #Display = 2, I want to display all the items for which ec.IsEquipmentRelated is true OR false. How can I implement this in the FROM section?
ALTER PROCEDURE [dbo].[Downtime_GetNewCause_EquimentLocation]
#DisplayInactive bit = 0,
#SortOrder INT = 0,
#Diplay INT = 0
AS
-- Main Data source
SELECT ic.IncidentCauseID
, 'EquimentRelated' = COALESCE(ec.IsEquipmentRelated, 0)
, ic.NewIncidentCauseID
, ic.DisplayName
, ic.IsLegacy
, el.EquipmentLocationID
, el.ShopID
, ec.EquipmentClassID
, ec.EquipmentAbbr
, el.ClassSequenceNumber
, el.EquipmentComponent
, el.CompSequenceNumber
, ic.IsActive
FROM Downtime_IncidentCauses ic
LEFT JOIN Downtime_EquipmentLocations el ON ic.EquipmentLocationID = el.EquipmentLocationID
LEFT JOIN Downtime_EquipmentClasses ec ON el.EquipmentClassID = ec.EquipmentClassID AND
CASE WHEN #Diplay = 0 THEN ...
CASE WHEN #Diplay = 1 THEN ...
CASE WHEN #Diplay = 2 THEN ...
This should work:
INNER JOIN Downtime_EquipmentClasses ec
ON (el.EquipmentClassID = ec.EquipmentClassID)
AND ( (#Display = 0 AND ec.IsEquipmentRelated = 1)
OR (#Display = 1 AND ec.IsEquipmentRelated = 0)
OR (#Display = 2) )
Do it in a WHERE clause:
WHERE (#Display = 0 AND ec.IsEquipmentRelated = 'True')
OR (#Display = 1 AND ec.IsEquipmentRelated = 'False')
OR #Display = 2