126

(2 replies, posted in General)

Wayne wrote:

Hi All,

I have a question about Windows 11, will our programs still work on windows 11?

Regards
Wayne

Using windows 11 now(dev-insider) and all is well.

Sometimes, when working with bunch of record/row in my database, complex calculated field make my application slow, even hang sometimes especially for the users with a low-spec computers. But then I use it(calculated) in some cases.


Trigger is a piece of code inside your database. you have to code it manually,
I'm putting some of the business logic inside the database using trigger., think of it as an auto-query triggered before/after insert, update and delete. with values NEW.[field] and OLD.[filed] which you can use to update/insert/delete other record from other table of the database.


You can search for "trigger in sqlite" for that.


Just be careful for updating fields on a table using MVD will delete the trigger or sometimes prevent updating it. My way of doing trigger is to have a file and save all triggers there. Here's a sample of my trigger to give you an idea

DROP TRIGGER IF EXISTS "main"."debit_post";
CREATE TRIGGER "main"."debit_post"
AFTER UPDATE OF "dbt_is_posted"
ON "debit"
WHEN ((OLD.dbt_is_posted=0) AND (NEW.dbt_is_posted=1))
BEGIN        
    DELETE FROM commitment_payment WHERE id_commitment in (SELECT DISTINCT(id_commitment) FROM debit_commitment WHERE id_debit=NEW.id);

    INSERT INTO commitment_payment(
        id_commitment, id_account, id_fms_budget, amt, dtime, id_debit    
    )
    SELECT 
        debit_commitment.id_commitment,
        fms_budget.id_account,
        fms_budget.id,
        CASE WHEN (debit_commitment.fms IS NOT NULL ) THEN 
            SUM(debit_commitment.dbtc_amt)
        ELSE 
            debit.dbt_amt
        END
        as amt,
        debit.dbt_dtime AS dtime,
        debit.id as dvid
    FROM debit_commitment
    LEFT JOIN debit ON debit.id=debit_commitment.id_debit
    LEFT JOIN fms_budget ON fms_budget.id = 
        CASE
            WHEN (debit_commitment.id_fms_budget IS NULL ) THEN debit_commitment.fms
            ELSE debit_commitment.id_fms_budget
        END
    WHERE id_debit=NEW.id
    GROUP BY CASE
        WHEN (debit_commitment.id_fms_budget IS NULL ) THEN debit_commitment.fms
        ELSE debit_commitment.id_fms_budget
    END, fms_budget.id_account;
    UPDATE bdcm SET dbt_is_posted = 1 WHERE id_debit = NEW.id;
END;

Then before updating field using MVD, I am deleting all triggers created then re-run it(copy-paste). I'm using Database manager(Navicat) when creating and updating triggers. Save so much time. There are free software too like DBeaver, DB Browser, etc. I think some of then can create trigger too with just a few clicks. But knowing how to construct it manually is a great advantage.


You can put aside trigger for now and try to study it first.

128

(6 replies, posted in Script)

Stock monitoring can be done in MVD. There are many way to achieve it.

You can elaborate more on what you are working on so that someone might help you.

I rarely use calculated fields on the applications I am working on. I rather use trigger or save-it-in-database. This might be a workaround on what you are looking for.


I also updated the filter date, since entering a record that will fall in the last day of the month will not be displayed on the search.
I just added 0.99999 (less than a millisecond/second for a day)


Try changing this line too

frmDetail.a_ampm.Text := FormatDateTime('AM/PM',frmDetail.dtpDate.DateTime);

to

frmDetail.a_ampm.Text := FormatDateTime('hh:nn AM/PM',frmDetail.dtpDate.DateTime);

It might be the one you are looking for. I just go with what your calculated fields do.


PS: I didn't change the report. just the saving part. You might want to just update it.

130

(11 replies, posted in General)

I found other fix to your problem, without using the function I gave, you can have extra sql query to get what you want

SQLExecute('PRAGMA case_sensitive_like=OFF');
If SqlExecute('Select Count(Id) From MyTable Where Col1 = "' + Form2.Edit_Col1.Text + '"') > 0 then
Begin
         MessageBox('Duplicate Record Exists - Cannot Save','Error',MB_OK+MB_ICONERROR);
         Cancel := True;
         Form2.Edit_Col1.SetFocus;
End;
SQLExecute('PRAGMA case_sensitive_like=ON'); // make sure to turn it on

131

(11 replies, posted in General)

if you are using this code

If SqlExecute('Select Count(Id) From MyTable Where Col1 = "' + Form2.Edit_Col1.Text + '"') > 0 then
      Begin
         MessageBox('Duplicate Record Exists - Cannot Save','Error',MB_OK+MB_ICONERROR);
         Cancel := True;
         Form2.Edit_Col1.SetFocus;
         Exit;
      End;

Then, you might want to change it to

procedure Save_Button_OnCLick();
var
   _chk: String;
begin
   _chk := SQLExecute('SELECT COALESCE(Col1, '''') FROM MyTable WHERE Col1 LIKE "' + Form2.Edit_Col1.Text + '" LIMIT 1');
   if CheckExactString(Form2.Edit_Col1.Text, _chk) then
   begin
         Cancel := True;
         Form2.Edit_Col1.SetFocus;
         Exit;
   end;
end;

132

(11 replies, posted in General)

procedures => do algorithm and/or process
function => will do algorithm and/or process then return a value

That function returns a boolean value so can use it on a condition like

if CheckExactString('Flag', 'Flag') then
begin
  // do something
end;

or


// If not the same
if (Not CheckExactString('Flag', 'flag')) then
begin
  // do something
end;

This might help you.

134

(11 replies, posted in General)

I'm not sure if this is what you are looking. It's a workaround on checking exact string

function CheckExactString(s1: String; s2: String): boolean;
begin
    result :=  (((PosEx(s1, s2)) = 1) AND (Length(s1)=Length(s2)));
end;

135

(11 replies, posted in General)

You're welcome.

I got here a procedure focusing the textbox. It's out of the topic but can help you save some time and have a better User Experience for your application

{
    Focus and select all text of a textbox
}
procedure FocusTBox(tb: TdbEdit);
begin
    tb.SelectAll;
    tb.SetFocus;
end;

Add it on your script, then change

Form2.Edit_Col1.SetFocus;

to

FocusTBox(Form2.Edit_Col1);

136

(2 replies, posted in SQL queries)

Try using

var dateHire : TDateTime;
dateHire := SQLDateTimeToDateTime(
    SQLExecute('SELECT dateHire FROM employee where ID = ' + frmEmpRecord.tbEmpID.Text+' LIMIT 1')
);

137

(11 replies, posted in General)

Frank,


Glad that you have fixed it. Well, MVD's really great in creating that kind of report for you. I've been trough a lot of SQL coding before(Web Development) just to create such reports and MVD simplified it all.


To fully understand what MVD's doing, you must learn a little bit of SQL Queries. You really must select from tbl_Service since that table handles the record(Master data) you are trying to display. You just have to LEFT JOIN it(Service) to tbl_Equp table to get the equip information.


MVD automatically creates that left join when you add equip field in your report. MVD will look on the reference for that table using the main table you select(tbl_Service in this case). MVD will find that reference(id_tbl_Equip) and join it to the table (tbl_Equip) to get equip details you ask MVD to fetch. Then if you add another table(in my example tbl_technician, it will look for id_tbl_technician and LEFT JOIN it to tbl_technician), and so on...


To sum it up, MVD creates SQL something like this behind that report button

SELECT
   tbl_Equip.eqName AS "tbl_Equip_eqName", 
   tbl_Service.s_date, 
   tbl_technician.t_name
FROM tbl_Service
LEFT JOIN tbl_Equip ON tbl_Equip.id = tbl_Service.id_tbl_Equp
LEFT JOIN tbl_technician ON tbl_technician.id = tbl_Service.id_tbl_technician 
WHERE tbl_Equip.eqNAME = "[Text_from_eqName_on_Form]"

Well, MVD is assigning each fields an alias using "AS" like I done in the first field.


Note: Just be careful with that kind of filter you used (eQName), Having 2 or more equipment with the same Name will ruin your report. It will display all services for all that equipment.

In deployment, there's more likely no equipment with the same name thou but if your application doesn't check it upon saving, then your application can have 2 or more equipment with the same(exact) name

138

(12 replies, posted in General)

kees.krause wrote:

Hi Brian,

Indeed this is a wonderfull example. I'm going to use it. I also like the used icons (menu,stock,inventory) Did you made them yourself or can I download them, and others in this series, from the internet?

I can't remember where I've downloaded it. But it was a premium Icon.


I am downloading icons here https://www.flaticon.com/ for now

139

(11 replies, posted in General)

It's hard to find the problem here Frank. I suggest you put all the SQL query here and maybe someone can point it out.


Here, I made an example. I hope you can get an idea from it.


On frmEquip, there are 2 Report buttons. First button will not work(not really, it just wont display equipment details) when no service is added to an equipment.


Report 2, on the other hand will display equipment even without service is added but will require additional script(well you can use that script later on especially when working with multi-table to display in a report)


PS: By the way, when you said tbl_SvcProc is a child, you mean in a service record you will have one or more procedure/s? I only make it as a connection in my sample

140

(12 replies, posted in General)

Have you considered using button images?

141

(16 replies, posted in Script)

I'm not sure to where you want the default settings to appear, when creating new record? it seems your button on Form1 is just a Show Form.

Anyway, for further samples, you can have a global variable which will be available to all your functions/procedures within your script that will handle the defaults.

142

(16 replies, posted in Script)

I recently adopted this kind of setup.

You can also use the TIniFile

Here, I made some changes with your example.

143

(6 replies, posted in General)

In Database,
Blue(Filled) = NULL
Hollow(Unchecked) = 0
Checked = 1

You can use the that filled when you are having a filter,
marking it as filled(blue) will give you both yes and no,
yes, for all checked,
no for all no or unchecked.

144

(6 replies, posted in General)

papafrankc wrote:

Brian,
Your fix does prevent the form from closing however now my SAVE button on the Equip form doesn't work.  It does appear to Save the info on the form but now it doesn't close the form.  The only way I can close the form is with the X on the top right of the form.
.
Sorry to be such a pain in the _ _ _.
Frank

Do the Tag Method and it will solve your problem

in the button (showing the frmService,

procedure frmEquip_[btnshowingfrmservice]_OnClick (Sender: TObject; var Cancel: boolean);
begin
    // if you are not using this button
    frmEquip.btnSave.Tag := 1; //
    // but if you already using btnSave.Tag somewhere else, you can use [btnshowingfrmservice]
    // frmEquip.[btnshowingfrmservice].Tag := 1; 
end;

When this tag is not 1, then close the form OnAfterClick of frmEquip.btnSave

procedure frmEquip_btnSave_OnAfterClick (Sender: TObject; var Cancel: boolean);
begin
    if frmEquip.btnSave.Tag <> 1 then
    // or if you use option 2,
    // if frmEquip.[btnshowingfrmservice].Tag <> 1 then
        frmEquip.Close;
end;

Take Note: Make sure you set the button tag to, 0, after opening frmService, of after saving

procedure frmService_btnSave_OnAfterClick (Sender: TObject);

var  TableID :integer;
begin
    TableID := frmEquip.btnSave.dbGeneralTableId; // GET THE FORM ID

    frmEquip.ShowRecord('tbl_Equip', TableID);  // UPDATE THE FORM

    // Make sure to set it not 1, 
    frmEquip.btnSave.Tag := 0; 
    // but if you already using btnSave.Tag somewhere else, you can use [btnshowingfrmservice]
    // frmEquip.[btnshowingfrmservice].Tag := 0; 
end;

145

(6 replies, posted in General)

Yes there is. Just Uncheck the "Close the current form after saving". Then to make sure that it won't add a record(which happens to me sometimes), set dbDontResetID of the frmEquip.btnSave to True from the onClick of the save button

procedure frmEquip_btnSave_OnClick (Sender: TObject; var Cancel: boolean);
begin
    frmEquip.btnSave.dbDontResetID := True;
end;

146

(6 replies, posted in General)

You can click the save button via script of FormA after or before opening FormB for it to save your unsaved data.

But if you are using NewRecord Method when opening FormB, this will automatically click the save button of FormA

If you have an after-save message on FormA save button, then you can trap it using the FormA.Tag condition method.

147

(7 replies, posted in General)

For Option 1, try putting your code in the OnAfterClick event of frmService.btnSave

148

(7 replies, posted in General)

papafrankc wrote:

Brian,
A couple of questions: Are you referring to Option 1 or Option 2?
Also do you want me to use the code for the Calculated field as the Query?
And if that's true do you want me to put the complete code into calcNextSvcDate.
.
Sorry, my Pascal skills are still at a pretty basic level.
.
Thanks, Frank

For the Option 2. Yes you need to put the complete code of the calcNextSvcDate, for it to update in the form.

149

(7 replies, posted in General)

Don't copy my sample query, you have to get the query from your calculated field you are trying to get. Can you go to your database and put here the calculated query (calcNextSvcDate) from the table tbl_Equip you are trying to access

150

(7 replies, posted in General)

papafrankc wrote:

Hi All,
I'm wondering if there is any way to update a calculated field on a form using script?
.
Form A has a calculated field - calcField
Form B performs some data entry that will affect calcField
.
However Form A is OPEN when I open Form B and make the data entry.
So when I close Form B, the calcField has not been updated.
When I close Form A and re-open it the calcField is correct.
.
Is there any way to update calcField on Form A without closing and re-opening it?
.
Thanks
Frank

Good day Frank,

I can think two way of doing this.

1. You can call the ShowRecord of the Form

FormA.ShowRecord('tblname', [currentid])

If you have a save button on FormA, then you can get its id by using the

FormA.savebtn.dbGeneralTableId

Problem with this approach is if you have a grid on FormA that handles child, then it'll be refreshed and losses its focus. If other problem arises, then use Option 2.
2. Do a sql query that will populate the calculated field(control). You can get your calculated field query from your db manager, then have it in your script. something like

FormA.calculatedControl.Value := SQLExecute('SELECT TOTAL(fld) FROM tbl WHERE id='+IntToStr(FormA.savebtn.dbGeneralTableId));

You can insert your script in the AfterClick event of the Save button of your FormB