451

(15 replies, posted in General)

Here you go Adam.

452

(8 replies, posted in General)

Kim, As far as your decimal points are concerned, if you change the field type to REAL in the Database Tables tab within MVD, you should be able to enter in decimals past 2. I changed it in your project you attached and I was able to enter in values such as 1.2345 and it showed that way in the grid.


Forgive me for my denseness. I'm trying to understand the range searches and the calculations you want. It might help if you would do a screenshot of your form and make annotations on it and submit it here so we can get a better feel for how the form should work.

453

(15 replies, posted in General)

See attached for hiding column. I'm not sure I understand your tax issue though.

454

(15 replies, posted in General)

Sorry Adam. Rushed through the solution I guess. Try attached.

455

(15 replies, posted in General)

In the fixed project I had to change your calculated fields in the SaleInv table. Change the cfSales calculated field to

select sum(saleinvitem.totalamt) 
from   saleinvitem 
where  saleinvitem.id_saleinv = saleinv.id
and    saleinv.id_dbcr = '1'

And change the cfRefunds to

select sum(saleinvitem.totalamt) 
from   saleinvitem 
where  saleinvitem.id_saleinv = saleinv.id
and    saleinv.id_dbcr = '2'

456

(15 replies, posted in General)

Project fixed. Since sales items belong to sales invoices and credit items belong to credit invoices, you no longer need the dbcr field in the sales items table. I removed it. I think you were getting confused with the timing of the "onAfterClick" event. From a parent form you were trying to manipulate properties on a subsequent form after the subsequent form was completed. Changing properties are typically (not always) done during the onShow event and OnChange events for an open form. Anyway, see if the attached project takes care of what you were trying to do.

457

(15 replies, posted in General)

Adam, First your DbCr table was empty (No sale and No Refund). I added them manually. Second, you tried to set the label caption and the color all in one statement. You can't really do that, so I separated them out for you.  See the attached for the fix.


Also, I'm assuming you realize that in this particular project, that your Save button will always add a new SaleInv record.

Dimitry, or anyone knowing this topic.   I know how to send parameters to another external program from an MVD program, but how do you read parameters received into an MVD program. I looked on Delphi Basics and see ParamStr and ParamCount, but apparently they are not defined in MVD. So how do you read parameters sent from another program?  Thank you.

459

(9 replies, posted in General)

Adam,  It's only one function. You just need to trap which button caused the constraint. You could do something like the following.

function OnSQLException(Sender: TObject; Msg: string; SQL: string): boolean;
begin
    if Pos('FOREIGN KEY constraint failed', Msg)=1 then
        begin
            result := True; // to prevent system message
            case sender of    // Each of the following messages should be customized for the appropriate delete
                 frmLookups.btnGenTaxRateDelete : MessageBox('Record cannot be deleted....', 'Error', MB_OK+MB_ICONWARNING);
                 frmLookups.btnGenCountryDelete : MessageBox('Record cannot be deleted....', 'Error', MB_OK+MB_ICONWARNING);
                 frmLookups.btnGenRetReasonDelete : MessageBox('Record cannot be deleted....', 'Error', MB_OK+MB_ICONWARNING);
            end;
        end;
end;

460

(13 replies, posted in General)

Kim,  Either way is acceptable. There really is no one right way. The one that works for you is the right way. My personal preference is to just do it through code. But I would still define the index on the database. If you go the database route, you may want to consider intercepting the constraint error message through code. The system generated error messages are not the most user friendly. Users may be confused as to what happened. Dimitry has provided a solution in this forum on how to intercept the SQL exception message and replace it with your own. I keep a folder of helpful scripts from this forum that I can use as a reference when I need it rather than trying to find the topic in the forum. Here is a general script to intercept the SQL constraint message for the Unique constraint and replace it with your own message.

// The following is an example for Unique Constraint error

// global event for all exceptions related database 
function OnSQLException(Sender: TObject; Msg: string; SQL: string): boolean;
begin
    // Exception when you use the functions SQLExecute or SQLQuery

    if Sender=nil  then
    begin
        if Pos('UNIQUE constraint failed', Msg)=1 then
        begin
          result := true; // to prevent system message
          MessageBox('Record already exists', 'Error', MB_OK+MB_ICONWARNING); // your message
        end;
    end;

    // Exception from MVD save operation assigned to a button

    if Sender = Form1.SaveButton then    // if exception from Form1.SaveButton
    begin
        if Pos('UNIQUE constraint failed', Msg)=1 then
        begin
            result := True; // to prevent system message
            MessageBox('Record already exists.', 'Error', MB_OK+MB_ICONWARNING);
        end;
    end;
end;

461

(5 replies, posted in General)

Adam, See attached for customer and product label fix. You do not need to fetch the names from the database. Since the names are already in the main tablegrids, I just pulled them from the grids instead. It eliminates an extra read to the database.


I'm not sure what causes the horizontal scroll bar flash. I have noticed that in my own projects too. Maybe Dimitry can provide an explanation.

462

(13 replies, posted in General)

Just substitute your Name and Surname fields where I have Col1 and Col2.

If SqlExecute('Select Count(Id) From MyTable Where Col1 = "' + Form2.Edit_Col1.Text + '" and Col2 = "'
      + Form2.Edit_Col2.Text + '"') > 0 then
      Begin
         MessageBox(Form2.Edit_Col1.Text + ' ' + Form2.Edit_Col2.Text + ' exist in the database.' + #10#13#10#13 + 'Duplicate record is not allowed - Cannot Save','Error',MB_OK+MB_ICONERROR);
         Cancel := True;
         Form2.Edit_Col1.SetFocus;
         Exit;
      End;

463

(13 replies, posted in General)

Adam, If both columns need to exist ("and condition") then change the If statement to the following:

If SqlExecute('Select Count(Id) From MyTable Where Col1 = "' + Form2.Edit_Col1.Text + '" and Col2 = "'
      + Form2.Edit_Col2.Text + '"') > 0 then

464

(13 replies, posted in General)

Kim, The example tcoton pointed out is an excellent example, but may be a bit more advanced for a newbie. I don't mean to insult your intelligence. If you understand that particular example, then disregard my example. I put together a very simple project for you to learn the concept.

See attached for one possible way of doing it.

466

(7 replies, posted in General)

Place your If statement in the password field (edPassword) OnChange event.

467

(7 replies, posted in General)

Adam, for number 2 you can place the following line in the field "Find What" OnKeyDown event:

If Key = 13 then Form1.FindNext_Button.Click;

For number 3 you need to click inside the time field on one of the time elements (hour, minute, or second) then click on the arrows.

468

(37 replies, posted in General)

Adam, I went ahead and put in a timer so if the app is still running over midnight, then the recurring process will run and you'll see the new recurring expenses populated in the tablegrid. The timer checks every minute so if you are watching and it does not populate right at midnight, wait a minute and it will.

469

(37 replies, posted in General)

Oh I see. No it's not going to run the process if you leave the app running over midnight. Do you really anticipate that happening from your users?

470

(37 replies, posted in General)

You do not need to restart the app. They should show after you do a save. Are you saying that they are not showing when you do a save? They do on my end. But if you want to place a dbUpdate in the script, don't create a button for that. Just place it inside the  "frmExpenses_Button_Save_OnAfterClick" procedure after the "If" statement.

471

(10 replies, posted in SQL queries)

Derek, Just to interject a thought here. I know you moved your SqlQuery into a script, but if you ever want to use SqlQuery in the future, you can still format your currency fields. I used to use a For loop through the tablegrid to format currencies, but Dimitry introduced in 3.3 the following component for formatting currencies in a tablegrid. I had to change my way of doing it because it stopped working in 3.3. There is a recent post in the forum regarding this subject.

if form1.TableGrid1.Columns[7] is TNxNumberColumn then
      begin
        TNxNumberColumn(form1.TableGrid1.Columns[7]).FormatMask := '#,###,##0.00';
      end;

472

(37 replies, posted in General)

I updated the project so you won't get the table not found on startup. Plus the save button will now catchup all recurring expenses for past dated recurring expenses and display them on the grid. I no longer empty your Recurring Boolean value and Recurring Every value. I let them alone so you can see that they are recurring expenses. However, I had to create another Boolean field in the Expenses table so I can check that field to see if a recurring record was created and turn it on if a recurring was created. The app, upon startup, will still check and create new future recurring expenses as their date arrives. I tested the app, but not necessarily an exhaustive test for time sake. If you start messing around with changing dates on past recurring expenses, there may be issues in the recurring process and possibly create duplicates. Therefore I disabled the expense date on past recurring expenses. I put some controls in place to try to prevent other problems. For instance, I do not allow a user to change the recurring date any longer. That date is controlled by the Recurring Every value and shouldn't be messed with. Try it out and give it a whirl.

473

(37 replies, posted in General)

Alright Adam, we are going to get you through this yet. The reason for the foreign constraint was that your category and group comboboxes were empty. I updated the project so you shouldn't get the error now. The database in the attached is empty so you can start fresh. Try it again.

474

(37 replies, posted in General)

Thank you Dimitry. That was quite obvious. I wasn't thinking along those lines for converting the date. Sometimes one can't see the forest for the trees :-)


Adam, the attached project has Dimitry's date fix and I put in what I think you want on a Save event. So  when saving a recurring event, the next recurring event will get populated and thus show on the tablegrid. From that point on the other process will keep up with recording future recurring expenses.

475

(12 replies, posted in Script)

What I do and I know it's not perfect is instead of assigning the password as a literal, I break the password down into pieces, one or two characters, and hide the pieces of the password on a form as labels.  You can place them on frmWait if you are using the Application.ProcessMessages or on your first form. I only use one character label names to conceal some more. Then in the password assignment I add each label caption together.

Like I said, it's not perfect, but the password does not pop out as a literal in the script.dcu file. It would take a little effort to figure it out and it would require knowledge of how MVD works behind the scenes. But I agree, it would be nice if the script.dcu file could somehow be embedded into the exe file.

Example:


frmMain.MySQLConnection.Password := frmWait.w.caption + frmWait.x.caption + frmWait.y.caption + frmWait.z.caption;