PenelopeSkye 1 Posted February 21, 2023 Unless I want to have a lot of undeclared identifiers I have to have multiple var sections, see below. That is so wrong! Also, this array declaration doesn't work under any circumstances even though I lifted it from another unit in the project and made sure it has the same uses list. x: array[0..9] of variant; The procedure in the other unit was not a (Sender: TObject) procedure (sorry for my ignorance of what to call that). What am I doing wrong? The list below has no errors when I put in all the var sections. procedure TfDesignMaster.PopulatePdlNotesWithValuePack(Sender: TObject); begin var stocknummm,value,value1,value2,keyfields, fieldname: string; var F: TField; var i: integer; var lresult: boolean; var fn:=tstringlist.create; var sl:=tstringlist.create; Share this post Link to post
Sherlock 663 Posted February 21, 2023 The var goes before the begin. procedure TfDesignMaster.PopulatePdlNotesWithValuePack(Sender: TObject); var stocknummm,value,value1,value2,keyfields, fieldname: string; F: TField; i: integer; lresult: boolean; fn: TStringList; sl: TStringList; begin fn:=tstringlist.create; sl:=tstringlist.create; Surprisingly the DocWiki does not clarify this: https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Variables_(Delphi) at least on that page. Share this post Link to post
programmerdelphi2k 237 Posted February 21, 2023 (edited) when using: Quote begin var MyVar: string; .... showmessage( MyVar ); ... end; you can understand like this: Quote begin var MyVar: string; BEGGIN .... showmessage( MyVar ); END; ... end; like into a "BLOCK" = SCOPE Edited February 21, 2023 by programmerdelphi2k Share this post Link to post
PeterBelow 239 Posted February 21, 2023 27 minutes ago, PenelopeSkye said: Unless I want to have a lot of undeclared identifiers I have to have multiple var sections, see below. That is so wrong! Also, this array declaration doesn't work under any circumstances even though I lifted it from another unit in the project and made sure it has the same uses list. x: array[0..9] of variant; The procedure in the other unit was not a (Sender: TObject) procedure (sorry for my ignorance of what to call that). There are two ways to declare variables inside a method or standalone procedure or function. Sherlock's reply shows the traditional way of declaring all variables in a single var section before the begin keyword that starts the body of the method. That has been part of the Pascal language since the time of its inception by Wirth; variables you declare this way are accessible in every place inside the body of the method. What you showed in your post is a fairly new way to declare variables inline, near the place of first use. In my opinion this should only be used if you need to reduce the scope of a variable to a specific block (e.g. a begin ... end block for an if statement or for loop). In fact in my real opinion it should not be used at all ; for one it is alien to the general structure of the language, and some IDE features do not work correctly (in the current version) when they are used, e.g. refactorings and things depending on the LSP server, like code completion. If you need a lot of variables in a method this is actually a "code smell", it indicates your method is too large and tries to do too many things. Refactor it to call several smaller methods that each do a single task. If that gets complex (i.e. you find you actually need a lot of methods to partition the code correctly) the solution may be to create a new class that does the required work internally and isolates it from the calling code. The array issue you mentioned probably has a different cause. If you declare a variable with a syntax like x: array [1..9] of variant; you are using what is called an anonymous type for the variable. This is allowed for classical variables declared at the top of the method but may not be allowed for inline variables. If in doubt declare a proper type and use that for the variable: procedure.... type T9Variants = array [1..9] of variant; var x: T9Variants; 2 Share this post Link to post
PenelopeSkye 1 Posted February 21, 2023 Oh my gosh, thank you so much!!! I combined your suggestions together and I am set!! Share this post Link to post
PenelopeSkye 1 Posted February 21, 2023 FYI I am trying to get the values from a query into an array. I am trying a lot of stuff cause I am not sure how I do it, hence all the variables! I will get rid of a lot of them once I figure out how to do this! Share this post Link to post
programmerdelphi2k 237 Posted February 21, 2023 (edited) I think that "a class" for this would help better than works with "variants", because you will need always "trusth" in each "variant value" when in use! using a class you can do it with more trusth (or same using a record type with all types-for-your-fields! some like this... // using a record for example type TMyRecordToManyTypes = record id: integer; name: string; birthday: TDate; active: boolean; end; procedure TForm1.procedureXXXXX(Sender: TObject); var MyDatas : TMyRecordToManyTypes; MyArrDatas: TArray<TMyRecordToManyTypes>; // same that: array of TMyRecordToManyTypes begin // where needs stored in your array of values while FDMemTable1.Eof do begin MyDatas.id := FDMemTable1.FieldByName('xxxx').AsInteger; // ... another fields... // MyArrDatas := MyArrDatas + [MyDatas]; // like a dictionary usage! end; // // if needs arbitrary values... // // MyDatas.id := 1; // MyDatas.name := 'hello world'; // MyDatas.birthday := now; // MyDatas.active := false; // // MyArrDatas := MyArrDatas + [MyDatas]; // // // when needs read it for var MyData in MyArrDatas do ShowMessage(MyData.name); end; Edited February 21, 2023 by programmerdelphi2k Share this post Link to post
PenelopeSkye 1 Posted February 21, 2023 Since you are kind enough to look into getting values from an array this is what I have so far. I can get the 2 values I want n each pass of the loop, but I want to be able to put both values together in a sentence and display them in a memo box. You were kind enough to provide code but will it work if I use the code below to get the both values into a sentence since it is already set up and the code above makes my brain hurt? I wish I were more experienced! Thanks! procedure TfDesignMaster.PopulatePdlNotesWithValuePack(Sender: TObject); begin //var designid: string; var stocknummm: string; var F: TField; stocknummm := dm.tb_design_master.fieldbyname('jmc_stock_num').asstring; ShowMessage(stocknummm); with dm do Begin q_GetStockNumFromValuePackLinks.SQL.Clear; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,Qty1 from ValuePackLinks where Pack_component1 = '+stocknummm) ; q_GetStockNumFromValuePackLinks.Open; while not q_GetStockNumFromValuePackLinks.EOF do begin for F in q_GetStockNumFromValuePackLinks.Fields do begin ShowMessage(F.Value); q_GetStockNumFromValuePackLinks.Next; end; q_GetStockNumFromValuePackLinks.Close; end; End; end; Share this post Link to post
programmerdelphi2k 237 Posted February 21, 2023 (edited) @PenelopeSkye if you necessity is just read and show the records, then, you dont needs so much... just use your SQL to find the record, and using a "While not xxxxx.EOF do..." it's enough! But you need read and store this values in some place (object, var, array, etc...) then, it's not more complicated too! look // defining my record-body... type TMyRecordToMyData = record ID: integer; // my EmpNo field FirstName: string; // my FirstName field // ... end; TMyArrOfMyDatas = TArray<TMyRecordToMyData>; // my dictionary for my datas procedure TForm1.Button1Click(Sender: TObject); var MyDatas : TMyRecordToMyData; // for each record readed in my table... MyArrOfMyDatas: TMyArrOfMyDatas; // like a dictionary off-line... LText : string; // just for tmp usage... begin // example: Employee (Interbase) from Embarcadero DB demo! // // Clearing and defining new "SQL" command... // 1º "empno" = field in the table // 2º "empno" = the "param name" that im using for indicating my Employee number... FDQuery1.Close; // always closing before any action... // // your select with your params, where, filter, etc... your SQL command!!! // the param-name can be any name, not used in reserved-word SQL!!! // // ex.: "select id, name from mytable where empno = :MyParamNameForEmpno" // FDQuery1.SQL.Text := 'select * from employee where empno = :empno'; // param-name = "empno" // FDQuery1.Params.ParamByName('empno').AsInteger := 2; // always using same param-name above! // FDQuery1.Open; // you can use "FDQuery1.Open( ' your SQL command here ' );" in some situations.... ok? // // simple way to catch all fields (if it can be casting to "string") for example!!! // no needs any "var, array, etc..." just read and write in your memo or any other target... while not FDQuery1.Eof do begin LText := ''; // for var i: integer := 0 to (FDQuery1.Fields.Count - 1) do // field name + field value LText := LText + FDQuery1.FieldDefs[i].Name + ' = ' + FDQuery1.Fields[i].AsString + slinebreak; // Memo1.Lines.Add(LText); // FDQuery1.Next; // to avoid "infinity looping" and catch next values... end; // // // another way, if you need store you values in a "array" or another type (class, record, etc...) // FDQuery1.First; // while not FDQuery1.Eof do begin // another ways: // FDQuery1.Fields.FieldByName('...').AsInteger; // FDQuery1.Fields[0].AsInteger; // FDQuery1.FieldByName('...').AsInteger; // etc... MyDatas.ID := FDQuery1['empno']; // FireDAC accept this way too! MyDatas.FirstName := FDQuery1['firstname']; // // building my list of datas MyArrOfMyDatas := MyArrOfMyDatas + [MyDatas]; // FDQuery1.Next; end; // for var MyData in MyArrOfMyDatas do Memo1.Lines.Add('ID=' + MyData.ID.ToString + ', Name=' + MyData.FirstName); // // you can delete an item in your array, dont worry, nothing will be delete from your table!!! // // let's say that exists 10 items, and you want delete the 2nd item just... no more! Delete(MyArrOfMyDatas, 2, 1); // deleting from 2º item, and only 1 item ... if exists, of course! // end; Edited February 21, 2023 by programmerdelphi2k Share this post Link to post
PenelopeSkye 1 Posted February 22, 2023 I have started working with your code, thank you so much for adding comments!!! I am having some issues that I am working on, I will post back here if I can't solve them if you wouldn't mind. Thank you! Share this post Link to post
PenelopeSkye 1 Posted February 22, 2023 I spoke too soon! It works! It feels too impersonal to thank your handle, so I shall call you Victor. Thank you so much Victor!!! Share this post Link to post
programmerdelphi2k 237 Posted February 22, 2023 (edited) not for that... call myself "Bond"... (... suspense music in the air...) ...James Bond 😂😁 Edited February 22, 2023 by programmerdelphi2k Share this post Link to post
PenelopeSkye 1 Posted February 22, 2023 LOL!!!!!! Well thank you James!!!!! Share this post Link to post
PenelopeSkye 1 Posted March 27, 2023 Hi James, I hope you will see this, I will wait a bit then post is in a new topic. I have a table with the following fields. It was not my design choice but I was overruled. I needed to search every pack_component field in every row for a specific value, so I chose union to bring that about. You gave me most of the code I used to create this procedure which finds the value and its' position and display it in a memo box. The code works perfectly but every now and then I get the attached error. Can you tell me why since the code works? Thank you! [vp_id] ,[Presentation] ,[Design_id] ,[Stock_pack] ,[Order1],[Pack_component1],[Qty1] ,[Order2],[Pack_component2],[Qty2] ,[Order3],[Pack_component3],[Qty3] ,[Order4],[Pack_component4],[Qty4] ,[Order5],[Pack_component5],[Qty5] ,[Order6],[Pack_component6],[Qty6] ,[Order7],[Pack_component7],[Qty7] ,[Order8],[Pack_component8],[Qty8] ,[Order9],[Pack_component9],[Qty9] ,[Order10],[Pack_component10],[Qty10] ,[Order11],[Pack_component11],[Qty11] ,[Order12],[Pack_component12],[Qty12] procedure TfDesignMaster.PopulatePdlNotesWithValuePack2(Sender: TObject); begin //var designid: string; var stocknummm,LText1,LText2,StockFromVP: string; var F: TField; stocknummm := dm.tb_design_master.fieldbyname('jmc_stock_num').asstring; StockFromVP := dm.tblValuePackLinks.fieldByName('Stock_pack').asString; Panel35.Visible :=false; Memo1.Clear; //ShowMessage(stocknummm); with dm do begin q_GetStockNumFromValuePackLinks.SQL.Clear; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,stockOrder = 1 from ValuePackLinks where Pack_component1 = ' +stocknummm ) ; q_GetStockNumFromValuePackLinks.SQL.Add('union' ) ; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,stockOrder = 2 from ValuePackLinks where Pack_component2 = ' +stocknummm ) ; q_GetStockNumFromValuePackLinks.SQL.Add('union ' ) ; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,stockOrder = 3 from ValuePackLinks where Pack_component3 = ' +stocknummm ) ; q_GetStockNumFromValuePackLinks.SQL.Add('union ' ) ; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,stockOrder = 4 from ValuePackLinks where Pack_component4 = ' +stocknummm ) ; q_GetStockNumFromValuePackLinks.SQL.Add('union ' ) ; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,stockOrder = 5 from ValuePackLinks where Pack_component5 = ' +stocknummm ) ; q_GetStockNumFromValuePackLinks.SQL.Add('union' ) ; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,stockOrder = 6 from ValuePackLinks where Pack_component6 = ' +stocknummm ) ; q_GetStockNumFromValuePackLinks.SQL.Add('union' ) ; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,stockOrder = 7 from ValuePackLinks where Pack_component7 = ' +stocknummm ) ; q_GetStockNumFromValuePackLinks.SQL.Add('union' ) ; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,stockOrder = 8 from ValuePackLinks where Pack_component8 = ' +stocknummm ) ; q_GetStockNumFromValuePackLinks.SQL.Add('union' ) ; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,stockOrder = 9 from ValuePackLinks where Pack_component9 = ' +stocknummm ) ; q_GetStockNumFromValuePackLinks.SQL.Add('union' ) ; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,stockOrder = 10 from ValuePackLinks where Pack_component10 = ' +stocknummm ) ; q_GetStockNumFromValuePackLinks.SQL.Add('union' ) ; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,stockOrder = 11 from ValuePackLinks where Pack_component11 = ' +stocknummm ) ; q_GetStockNumFromValuePackLinks.SQL.Add('union' ) ; q_GetStockNumFromValuePackLinks.SQL.Add('select Stock_pack,stockOrder = 12 from ValuePackLinks where Pack_component12 = ' +stocknummm ) ; //ShowMessage( q_GetStockNumFromValuePackLinks.SQL.Text) ; q_GetStockNumFromValuePackLinks.Open; while not q_GetStockNumFromValuePackLinks.EOF do begin for F in q_GetStockNumFromValuePackLinks.Fields do begin LText1 := ''; // for var i: integer := 0 to (q_GetStockNumFromValuePackLinks.Fields.Count - 1) do // field name + field value LText1 := q_GetStockNumFromValuePackLinks.Fields[0].Value; LText2 := q_GetStockNumFromValuePackLinks.Fields[1].Value; //ShowMessage(LText1); dm.q_GetStockNumFromValuePackLinks.Next; // to avoid "infinity looping" and catch next values... end; //ShowMessage(LText1); if q_GetStockNumFromValuePackLinks.Fields[0].Value <> '' then Panel35.Visible :=true else Panel35.Visible :=false; q_GetStockNumFromValuePackLinks.Next; end; Memo1.Lines.Add('Bag '+stocknummm+' is in Value Pack ('+LText1+') in Position (' +LText2+')' ); q_GetStockNumFromValuePackLinks.Close; end; end; Share this post Link to post
programmerdelphi2k 237 Posted March 27, 2023 (edited) your initial error is in .Add('select Stock_pack,stockOrder = 1 from ValuePackLinks where Pack_component1 = ' +stocknummm ) ; try some like this: procedure TForm1.Button1Click(Sender: TObject); const LSQLSelect: string = 'SELECT xFieldx from xTablex WHERE yFieldy = %d'; var LValues : TArray<integer>; LSQLText: string; begin for var i: integer := 1 to 10 do // just for test values... not necessar! LValues := LValues + [i]; // LSQLText := ''; // for var i in LValues do // more quick than use a component.property LSQLText := LSQLText + '***' + Format(LSQLSelect, [i]); // + slinebreak + ' UNION ' + slinebreak; // if not(LSQLText.IsEmpty) then begin // LSQLText := LSQLText.Remove(0, 3); // remove 3 chars on init... '***'; LSQLText := LSQLText.Remove(0, 3).Replace('***', slinebreak + ' UNION ' + slinebreak); // replace '***' for another text // Memo1.Text := LSQLText; // // if all it's ok, then you can use it: MyFDQuery.SQL.Text := LSQLText; // directly end; end; end. Edited March 27, 2023 by programmerdelphi2k Share this post Link to post
programmerdelphi2k 237 Posted March 27, 2023 you can use "Format(...)" function to replace values in your string: Quote LSQLText := Format('SELECT %s from %s WHERE %s = %d', ['field1', 'table1', 'field2', 12345 ]); you can try use "MACRO" in FireDAC, too: Quote SELECT !FieldX from !TableX where !FieldY !Sign !FieldValue ... for each macro type/value you create your Param definitions: MyMacro:= qryMain.Macros.Add; MyMacro.Name := 'xxxxx'; MyMacro.DataType := TFDMacroDataType.mdString; MyMacro.Value := 'xxxxx'; .... see on Help for more details!!! Share this post Link to post
programmerdelphi2k 237 Posted March 27, 2023 more one tip: "IF" (I said "IF") possible, forget "WITH" usage... mainly when for while... it's very confused... when you are a "master", then, all it's allowed 🙂 Share this post Link to post
programmerdelphi2k 237 Posted March 27, 2023 another BIG TIP... when you're posting a "CODE" like above use the button and choice "Delphi" as your language and "Insert..." next, next... Share this post Link to post
PenelopeSkye 1 Posted March 27, 2023 Doh! It should have been obvious that that button is what brackets code! Thank you! I am going to start studying the code you gave my above until I understand it, thanks again James! Share this post Link to post
Brian Evans 109 Posted March 27, 2023 (edited) What database? Some databases have UNPIVOT to more easily convert columns to rows (the reverse of PIVOT which converts rows to columns). Edited March 27, 2023 by Brian Evans Share this post Link to post