1

(14 replies, posted in Script)

There are two ways of centering a header.

1. (and the easiest)  use the options in settings for the tablegrid as per image attached.


2. In script   Form1.TABLE.columns[column number].Header.Alignment := taCenter;

2

(7 replies, posted in Script)

Kees,


Quite simply Derek's program shows you how to use the application.user.xxxxx . In his example he has attached them to a label, you could instead display them in a form caption or an edit box.


Your question was , "How can I present user data on a form?", and Derek's program shows you one way of doing this. I assume you have run his program.


I take it from your question, that you are wanting to do more than just display a user on a form or are you wanting display a selection of users?


I suggest if you need an answer closer to your requirements either attach your program so far to a post and state what it is you are hoping to achieve or explain more precisely what it is your are trying to do.

3

(2 replies, posted in SQL queries)

Zahar2002,


Search the web for a program called DyBase, it doesn't appear to be supported anymore, the website and instructions are in Russian, but it is similar to MVD but purely for Access databases.

Here is an example from my program:


procedure frmMain_tgOrders_OnChange (Sender: TObject);
CONST
    DATE_ORD = 5; DATE_PO = 7; DATE_REQ = 8; ORD_QTY = 9; ORDER_REC = 10; DUE = 11;
var
row, column, rowcnt, colcnt: integer;
begin

   rowcnt := frmMain.tgOrders.RowCount -1;
   colcnt := frmMain.tgOrders.Columns.Count -1;

   frmMain.tgOrders.BeginUpdate;
   for row := 0 to rowcnt do
   begin
       if frmMain.tgOrders.Cells[DUE,row] = '0' then     //Complete order received colour red/pink
       begin
           for column := 0 to colcnt do
           begin
               frmMain.tgOrders.Cell[column,row].Color := $00BDA8FD;
           end;
      end
      else
      
      {Part order received   colour Blue}
          if (frmMain.tgOrders.Cells[DUE,row] < frmMain.tgOrders.Cells[ORD_QTY,row])    then     //Complete order received
           begin
               for column := 0 to colcnt do
               begin                                       //light blue
                   frmMain.tgOrders.Cell[column,row].Color :=$00FFFFA8; // interesting brown $0065AACD;
               end;
          end
    
      else
    
        {Quote pending colour green}
          if (frmMain.tgOrders.Cells[DATE_REQ,row] <> '') AND (frmMain.tgOrders.Cells[DATE_PO,row] ='') then
           begin
               for column := 0 to colcnt do
               begin                                          //light green
                   frmMain.tgOrders.Cell[column,row].Color := $00B4F2B6;
               end;
          end
    
      else
    

    {To be ordered colour yellow}
    if  ((frmMain.tgOrders.Cells[DATE_ORD,row] = '')AND (frmMain.tgOrders.Cells[DATE_PO,row] ='') AND (frmMain.tgOrders.Cells[DATE_REQ,row]= '')) then
       begin
           for column := 0 to colcnt do
           begin                                          //light yellow
               frmMain.tgOrders.Cell[column,row].Color := $0080FFFF;
           end;
      end;

   end;
  frmMain.tgOrders.EndUpdate;

end;

5

(2 replies, posted in Script)

SQLExecute(INSERT INTO sal (books) VALUES ("'+form2.ComboBox2.Text+'")');

6

(4 replies, posted in General)

Here you go Unforgettable.


This program is one I use to test out things.   All you need to look at is the drop down box. I have used the code in the 'On Close Up' event.

You could if you wished put the calling code in the 'OnClick' event or even have a button with the calling code in.


To use, just type a word into the drop down box without opening the drop down. It will then appear in the table grid and also in the drop down list after you have clicked outside the combobox.

7

(6 replies, posted in General)

I can't get the above code to work for me.


I am using the Login form and have inserted the above code in the global begin....end.


It doesn't matter if I have the code at the beginning or end of the code block, what I get on startup is the message telling me the program is already running, even on first instance.  It then goes on to open the login form and opens the main form.

If I move the code into my Mainfrm.show  it ignores the code completely.


begin

   frmdbCoreLogin.Caption := 'Workshop Parts Login';

   {logo is copyright free from  https://unsplash.com/photos/jXd2FSvcRr8 }
 frmdbCoreLogin.Image1.Picture.loadfromfile((ExtractFilePath(Application.ExeName)+ 'WOS_login.jpg'));

 if FindWindow(nil, 'workshopPartsDB') <> 0 then
  begin
     showmessage('already running');
     frmdbCoreLogin.Close;
  end;

I have even tried :

if FindWindow(nil, ExtractFileName(Application.ExeName)) <> 0 then
  begin
     showmessage('already running');
     frmdbCoreLogin.Close;
  end;

And that doesn't work at all!


I have just had a further fiddle and checked the result of the FindWindow function, and, it is always 0, so no wonder the code doesn't work.

I'm running on Windows 10 64bit.

8

(4 replies, posted in General)

unforgettable,


By editable do you just want to be able to add items to the combobox or edit them as well?

To add an item directly to the combobox:


 { Function to check if  combobox has had a new item added to it}

 frmEditPart.cmbEditCategory.dbItemID := add2ComboBox(frmEditPart.cmbEditCategory.text, frmEditPart.cmbEditCategory.dbItemID);



{function to allow selected comboboxes to have new data added to them directly}


function add2ComboBox (Sender: String;  indx: Integer): Integer;
begin
   if (indx = -1)  AND (Sender <> '') then
       begin
         SQLExecute('INSERT INTO table (field) VALUES ("'+Sender+'")');
         UpdateDatabase('TABLE');
         Result := Last_Insert_id;
         showmessage('TABLE updated with '+Sender )
      end
      else begin
       Result := indx;
   end;


end; 

9

(7 replies, posted in Script)

Does this help?


Login Form attributes.

Form = frmdbCoreLogin

Form Components:
Image1  = picture
bLogin  = login button
pnPassword =
edPassword = password edit box
pnLogin
edLogin = login edit box

frmdbCoreUserForm.ShowModal;
frmMain.mniChangePassword.click;
frmdbCoreUserChangePwd.show;
frmdbCoreUsers.ShowModal;
frmMain.mniUsers.click;

frmdbCoreLogin.Caption:=strCaption;  
 frmdbCoreLogin.Image1.Picture.LoadFromFile(ExtractFilePath(Application.ExeName)+'Images\logo.png');    //load custom image
 
 Application.User.id;
Application.User.Username;
Application.User.Email; 
Application.User.First_name; 
Application.User.Last_name; 
Application.User.Role; 
Application.User.RoleId; 
Application.User.is_admin; 
Application.User.is_active;
Application.User.is_logged; 
Application.User.Last_login; 
Application.User.Date_joined;
 

10

(5 replies, posted in Script)

Hi salahnecibi,



If you have table grid then try something like this.



procedure frmMyForm_grdTableGrid_OnCellClick (Sender: TObject; ACol, ARow: Integer);
var
    id: integer;
begin
   id := (frmMyForm.grdTableGrid.dbItemID); // Get ID

   id := id + 1; //increment ID

// use this if you want to fill the edit box before you do the database search
  frmMyForm.edtEditBox.Text := intToStr(id);  

 // use this if for some reason if you want to keep th eID number for use elswhere in your program
   frmMyForm.edtIDEditBox.Text := sqlExecute('SELECT id FROM TABLE WHERE id="'+intToStr(id)+'"');
end;

If you are not using a table grid then just shout and alternative code can be provided.

11

(4 replies, posted in General)

Papafrankc,


I don't have an answer to your problem but, I think once you have solved the problem your end users will not see this, but each time you compile the program you might have to recheck all your drop down boxes before distributing your program.



As an example my project suffers from two annoyances.


1. A group box and labels keep moving each time I compile the program.
2. My date time pickers like to untick themselves between compilations.

So I have to test to make sure after I have added a new form or script code that these items are reflecting what I want before I recompile.

I suspect your dropdown box problem may well require a similar approach.

12

(4 replies, posted in General)

Is this a PDF link saved in a database?

If it is the following code relies on Windows associating file types and will automatically open the correct program.

procedure frmMain_btnOpenPDF_OnClick (Sender: TObject; var Cancel: boolean);
var
  fName :string;
begin
  fName := SQLExecute('SELECT DISTINCT File_Filename FROM SomeTable WHERE id = '+frmMain.tgTable.SQLValue);
  OpenFile(fName); 


Alternatively if you only ever want to open a PDF file then the above becomes



var
  fName :string;
begin
  fName := SQLExecute('SELECT DISTINCT File_Filename FROM SomeTable WHERE id = '+frmMain.tgTable.SQLValue);
  OpenFile(fName,'AcroRD32.exe'); 

If you are not getting the file name from a database link, just substitute the fName :=  with path and file name of the file you want opened.  Obviously you could add in an OpenDialog if you want the user to search for a file or have an edit box for the user to fill out a name etc.

13

(2 replies, posted in Russian)

Согласно StackOverflow, единственный способ сделать текст в окне сообщения или диалоговом окне сообщения жирным шрифтом - это создать новый класс или создать собственное окно сообщения.


Основные шаги создания такой формы:
1. создать новую форму
2. Добавьте метку и две кнопки
3. Установите для надписи жирный шрифт.
4. добавить обработчик к обеим кнопкам, закрыв форму и установив какое-то свойство, для которого была нажата кнопка.


https://stackoverflow.com/questions/225 … messagebox



According to StackOverflow the only way you can make the text in messagebox or messgedialog bold, is to either create a new class or design your own message box.


The basics steps of creating such a form:
1.Create a new form
2.Add a label and two buttons
3.Set the label font to Bold
4.add handler to both buttons, closing the form and setting some property for which button was pressed.

https://stackoverflow.com/questions/225 … messagebox

Thanks EHWagner,


The code isn't working in Outlook when I tested it today, I just get the HTML as text. However, I discovered a parameter that I will try tomorrow which might just change that.

I read at Microsoft that the oleobject for Outlook includes object.HTMLBody  and I was using object.body.


So, tomorrow when I have access to Outlook, I'll give it a try and see what happens.

15

(10 replies, posted in General)

Hi Kees,


I think Brian means using a file similar to MVD's 'Settings.ini'.

To load a ini file use code similar to:


procedure loadSettings;
var
  settingsIni : TStringlist;
  lngth : integer;
begin
   settingsIni := TStringList.Create;
   settingsIni.LoadFromFile ('Settings.ini');
   dbName := SettingsIni[4];
   SettingsIni.free;
   lngth := Length(dbName) - 7;
   dbName := copy(dbName, 8, lngth);
   FrmMain.lbDbPath.Caption := ExtractFilePath(Application.ExeName)+ dbName;
end;

That code is for loading the standard settings.ini file and finding the name of the database.

To save a file change LoadFromFile to SaveToFile .

16

(31 replies, posted in General)

Papafrankc,

In the code you provided, you haven't assigned the text in your edit box to sKey.

Assuming you have sKey as a string type variable you need -

sKey := formName.EditBoxName.text;

I'm trying to take the contents of a tablegrid and  convert it to HTML for the body of an email.


My problem is that I only seem to get one complete row and the first two columns into the second row into HTML.
I'm practising with a tablegrid that has four columns and five rows.


The code I'm using is below

   sList:TstringList;
begin
         sList:=TStringList.Create;
         sList.Add('<html>');
         sList.Add('<head>');
         sList.add('<style>');
         sList.Add('table, th, td {');
         sList.Add(' border: 1px solid #dddddd; text-align: left; padding: 8px');
         sList.Add('}');
         sList.Add('</style>');
         sList.add('</head>');
         sList.Add('<body>');
         sList.Add('<table>');
         sList.Add('<tr><th>BSuite#:</th>'+ '<th>Part Number</th>' + '<th>Description'+ '</th>'+'<th>Qty'+'</th></tr>');

         for indx := 0 to frmEmail.tgEmailList.RowCount-1 do
         begin
            sList.Add('<tr><td>'+frmEmail.tgEmailList.Cells[0,indx] + '</td>' + '<td>' +frmEmail.tgEmailList.Cells[1,indx] +'</td>'+'<td>'+frmEmail.tgEmailList.Cells[2,indx]+'</td>'+'<td>'+frmEmail.tgEmailList.Cells[3,indx]+'</td></tr>');
         end;
         sList.Add('</table>');
         sList.Add('</body>');
         sList.Add('</html>');

        openURL('mailto:'+frmEmail.cmbEmailAddress.Text+'?subject='+frmEmail.cmbSupplierList.Text+'Order'+'&Body='+sList.text);
sList.Free;

I'm just not seeing why I'm only getting 1 and a bit rows.  This will be going into Outlook, but  my personal email client (emClient) has to have the HTML input manually. My suspicion is that I'm missing an HTML tag, but I can't see where!


Any thoughts gratefully received.

18

(6 replies, posted in General)

Hi Blackpearl8543,


I don't know how to close an MVD program by checking Windows processes as I don't think th ePascal Script allows access to the THandle type.


However, if you have your users 'login' then you can use the following script .


//user_log.pas
var
  logged_in : boolean = False;

procedure ClearLogs;
begin
    SqlExecute('DELETE FROM user_log WHERE username = "' + Application.User.Username + '"');
end;

procedure startLogs;
begin
   If SqlExecute('SELECT count(username) FROM user_log WHERE username = "' + Application.User.Username + '"') > 0 then
     Begin
        MessageBox(Application.User.Username + ' is already logged in.' + #13#10#13#10 + 'If this is not correct, please see your administrator.','Login Problem',MB_OK+MB_ICONERROR);
        frmMain.Close;
     End;
   
   frmMain.lbMainUser.Caption := 'Current User is: ' +Application.User.First_name + ' ' + Application.User.Last_name+'  Role: '+Application.User.Role+'  Last Login: '+DateToStr(Application.User.Last_Login);
   SqlExecute('INSERT INTO user_log (username,Logged_In,isLogged_In) VALUES ("' + Application.User.Username + '","' + FormatDateTime('YYYY-MM-DD hh:nnampm',Application.User.last_login) +'",1)'); 
   logged_in := True;  
end;

procedure frmMain_tgLogged_OnCellDoubleClick (Sender: TObject; ACol, ARow: Integer);
begin
       showmessage(frmMain.tgLogged.Cells[ACol,ARow] +' '+frmMain.tgLogged.sqlValue);
       SqlExecute('Delete FROM user_log WHERE username = "' + frmMain.tgLogged.sqlValue + '"');
end;


begin
end.

You can remove the messagebox code and just go straight to formMain.Close

19

(31 replies, posted in General)

Papafrankc


JB is the man to ask as that is his code snippet.


I'd be wary about saving the serial numbers to a table unless you can encode them (which is possible) as otherwise anyone with copy of SQL Browser or SQL Studio would be able to open the database, read and take your keys.


To save the key to registry all you need is to write:

reg.WriteString('Key', 'sKey');

Assuming that sKey now contains the serial entered via your textbox.

20

(31 replies, posted in General)

papafrankc wrote:

CDB,

So I'm guessing there should be a form called frmNagScreen


Yes


Is there a standard NagScreen form I can use or do I have to create one myself?
Thanks, Frank


You need to create it yourself.  As you are creating the form yourself, you can call it whatever you want, making the appropriate changes in the code to reflect your choice of name.

21

(31 replies, posted in General)

Papafrankc,

I think this needs to be a global constant, so will need to be at the top of the script file, before any procedure or functions.

You can either write:
CONST
   APP_NAME = 'records.exe';

and then in the function   APP_NAME

or

CONST
   APP_NAME = records.exe;

in the nag screen function  'APP_NAME' either should work.


If you copied and pasted JB's code, you might have missed changing some of Jean's frmNagScreen to the name of your own 'nag' forms' name.

PS. Sorry JB I didn't see your reply when I was typing mine.

22

(31 replies, posted in General)

papafrankc,


Did you try substituting APP_NAME  with the actual name of your program, or, make a constant called APP_NAME referring to your program name including the .exe?

A possible but unsatisfactory workaround is to use a try.... except wrap-around.

try
      Outlook := CreateOleObject('Outlook.Application');



    vMailItem := Outlook.GetNamespace('MAPI');

    vMailItem.Logon;
    vMailItem := Outlook.CreateItem(olMailItem);
    vMailItem.Recipients.Add('dibbledabble@somewhere.someplace');
    vMailItem.Subject := 'What a wonderful test email';
    vMailItem.Body := 'This is a test --> how amazing';
    vMailItem.Send;
    Outlook := nil;
    except
     openFile('mailto:?Subject=PURCHASE ORDER PO: 123 &Body= no outlook installed')
 end;

I attempted to use this code suggested by Dmitry -  http://myvisualdatabase.com/forum/viewt … 702#p31702  to determine if Outlook is installed on a users PC.


This fails on two points when compiling.


1.  The type TCLSID  is not recognised.


2. The function CLSIDFromProgID  causes an error 'Undeclared identifier'.


Has this type and function not been included in MVD 6.4, or is there an alternative call?



The code I've written.


function CheckAppInStalled(AValue: String): boolean;
var
    FCLSID: TCLSID;
begin

    Result := (CLSIDFromProgID(PChar(AValue), FCLSID) = S_OK);

end;


procedure Form1_Button2_OnClick (Sender: TObject; var Cancel: boolean);
const
  olMailItem = 0;
var
  
  Outlook: Variant;
  vMailItem: variant;
begin
 
   if CheckAppInstalled('Outlook.Application') then
   begin
      Outlook := CreateOleObject('Outlook.Application');
   
      vMailItem := Outlook.GetNamespace('MAPI');
      vMailItem.Logon;
      vMailItem := Outlook.CreateItem(olMailItem);
      vMailItem.Recipients.Add('dibbledabble@somewhere.someplace');
      vMailItem.Subject := 'What a wonderful test email';
      vMailItem.Body := 'This is a test --> how amazing';
      vMailItem.Send;
      Outlook := nil;
  end
  else begin  // open non outlook installed client
     openFile('mailto:?Subject=PURCHASE ORDER PO: 123 &Body= no outlook installed')
  end;
end;

Hi dbk,

First I should note that using the above code you never see your email message, by that I mean the email is created and sent 'behind the scenes', unlike using mailto: or openfile(mailto:) which opens the email create page.

I don't know the answer to the rest of your question. I do know that the Outlook object has a number of item folders that can be searched such as contacts, calendar, email folders.

This link to Microsoft might help https://docs.microsoft.com/en-us/previo … office.11)

or

http://delphi-kb.blogspot.com/2011/06/o … _6280.html