Jump to content

Ian Branch

Members
  • Content Count

    1272
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by Ian Branch

  1. Ian Branch

    Fill Class Variables from a table row??

    Hi Uwe, I am coming to grips with this methodology. I need to change a few things. Not the least of which is the order of the variables in the Class to match the order of records in the Company table. So, it occurred to me, is it possible to add the variables dynamically? i.e. The Class starts out without any variables defined and then programmatically the variables and values are added based on the field name & value? Or possibly all the variables are added as variants and then the assignment of the value from the fields sets the variant type?? This would add enormously to the whole package flexibility/usability. Don't sweat on it, just thinking out loud here... 😉 Regards, Ian
  2. Ian Branch

    Fill Class Variables from a table row??

    Tks Uwe, I haven't fully digested your first Unit yet, just a quick look, when I do I will then go through this one. A quick look suggests I have a couple of other applications I can use it in as well. There is another thread in the Forum that I guess this is indirectly related to... Thanks Again, Regards, Ian
  3. Ian Branch

    Fill Class Variables from a table row??

    Hi Lars, It is the User's Company and the User is only associated with one company so that Company table row/data is loaded to TCompany. There are multiple Users, 80+, with 3 Companies in the Company table. Each User has a Unique UserID related to one of the companies. When they log in their related Company details are loaded to TCompany for use throughout the various units in the App(s). In essence, this is my way of having Global Company variables. Ian
  4. Ian Branch

    Fill Class Variables from a table row??

    Hi Lars, Please clarify what you mean? I am not 100% into this instancing stuff. If you are referring to keeping the Company table open and using its normal field addressing, for various reasons not for here, I don't want to. If you are referring to something else, I am all ears... :-) Regards, Ian
  5. Ian Branch

    Fill Class Variables from a table row??

    Hi Uwe, Thank you for your input. The CompanyData Unit is normally populated in the App's DataModule by simple assignment.. uses CompnyData; .... .... Company.Open; TCompanyData.mlcApplicationGlobalEmails := Company.FieldByName('ApplicationGlobalEmails').AsBoolean; ... ... Company.Close; ... ... I am using the unit in various other Apps/Units to pass around the Company Record field values without having to keep the Company table open. So, in various App/Units I might have something like.. uses CompanyData; .. .. ... if TCompanyData.mlcApplicationGlobalEmails then do something else don't; If there is a better way to do this I am open to suggestions.. FWIW I have attached the full Unit. Regards, Ian CompanyData.zip
  6. Ian Branch

    GExperts 1.3.20 experimental twm 2022-01-30 released

    Hi Thomas, Thank you once again for all your work on and support for GExperts. Greatly appreciated. Ian
  7. Hi Team, D10.4.1, Win 10. Of late when I start D10.4.1 I have been getting the above error message as Delphi/IDE starts up. It used to happen infrequently and closing/restarting Delphi normally restored normal service. Of late it has become more prevalent requiring multiple restarts of Delphi before a normal start happens. If I OK the error and let it continue I end up with Delphi windows scattered on the screen. I have done a search of all .pas & .dfm files on my PC and can't find any 'DotNetForm' component. I have also removed third party stuff like GExperts & cnPack but it still persists. Open to any thoughts/suggestions. Regards & TIA, Ian
  8. Ian Branch

    Spell Checker implementation?

    Hi Team, FWIW I had been wanting to add spell checking to my Apps for some time (years) but never got around to it. 😞 Based on the @Alexander Halser post above I bit the bullet and purchased Addict 4, gulp! - AU$490, perhaps I should have waited for the exchange rate to improve..nahh, I should live that long, and installed and integrated NHunspell. Per his offer, Alexander was gracious enough to send me his current NHunspell files. Thanks Alexander. I contacted Glenn Crouch from ESBConsult and he sent me his current Addict4 files for D11. Thanks Glenn. They work for D10.4.2 as well. After a short learning curve I now have spell checking operational in my Apps. It was relatively painless. 🙂 My only question is about the currency of the actual dictionary .oxt files/data. The dict-en.oxt file I have suggests it is from July 2010. Is this still current or is there a more recent version? Is there any value in sourcing a more recent file? If so where from? I'm figuring it doesn't really matter, dictionaries wouldn't change all that much and any new words can be added as part of Addict's interface. Regards, Ian
  9. Ian Branch

    Printing in Dark Mode????

    Hi Team, Is it just my environment??? I thought I would give Delphi Dark Mode a try. Seems OK while working /developing. Not overly enthused about it but willing to let it grow on me. I printed a small unit.. WTH!! Unreadable. All the white text on the screen was printed white on the printer. Ummmm. Is there a fix for this or do I have to switch to an IDE lighter mode before printing?? Yes, I print in Colour but I would have thought this would have been accommodated. Regards, Ian
  10. Ian Branch

    Printing in Dark Mode????

    Bad news then! Nothings been done on this matter since 10.3! 😞
  11. Ian Branch

    Printing in Dark Mode????

    Hi Team, Turns out, perhaps not surprisingly, that there is already an RSP for this from D10.3. https://quality.embarcadero.com/browse/RSP-31142?jql=text%20~%20%22Print%22 Feel free to vote for it, I have. Don't know if there is any way to escalate it into D10.4.2 or D11 issue notice. Ian
  12. Ian Branch

    Printing in Dark Mode????

    Let's just say I am on the wrong side of 70 and I prefer to sit down with a cuppa and a piece of paper and read through a new piece of code, making notes on the paper as I go. In this case it was only a small unit. Most cases I just print longer function and/or procedures so I can digest them. Old habits die hard.....
  13. Hi Edwin, Just looking at adding spell checking to my Apps. D10.4.2 son to be D11. Win 32 Apps. No Unicode. You say you have modified it for Unicode, will it still work OK for ANSI? Which libhunspell.dll does it need/use? Regards & TIA, Ian
  14. Hi Team, Any idea why only 7 procedures/functions are being shown in the attached image when there are clearly many more?? Regards & TIA, Ian Screenshot_9.bmp
  15. Ian Branch

    Missing procedures/functions in lookup??

    Grrrrr!!! Checking through other Units/Projects I have found repeated instances of this happening where I have declared in-line variables. :-( Back to the old/original way of declaring them..
  16. Ian Branch

    Missing procedures/functions in lookup??

    Great Call Uwe, If I comment out this function.. function ValidEmail(const EmailAddress: string): Boolean; const EMAIL_REGEX = '^((?>[a-zA-Z\d!#$%&''*+\-/=?^_`{|}~]+\x20*|"((?=[\x01-\x7f])' + '[^"\\]|\\[\x01-\x7f])*"\x20*)*(?<angle><))?((?!\.)' + '(?>\.?[a-zA-Z\d!#$%&''*+\-/=?^_`{|}~]+)+|"((?=[\x01-\x7f])' + '[^"\\]|\\[\x01-\x7f])*")@(((?!-)[a-zA-Z\d\-]+(?<!-)\.)+[a-zA-Z]' + '{2,}|\[(((?(?<!\[)\.)(25[0-5]|2[0-4]\d|[01]?\d?\d))' + '{4}|[a-zA-Z\d\-]*[a-zA-Z\d]:((?=[\x01-\x7f])[^\\\[\]]|\\' + '[\x01-\x7f])+)\])(?(angle)>)$'; var Emails: TStringList; begin Result := True; Emails := TStringList.Create; try Emails.Delimiter := ';'; Emails.StrictDelimiter := True; Emails.DelimitedText := EmailAddress; for var I := 0 to Emails.Count - 1 do if not TRegEx.IsMatch(Emails[I], EMAIL_REGEX) then begin Result := False; Break; end; finally Emails.Free; end; // end; Then all the procedures/functions show. Through a process of trial and error I found that if I change the code to the following.. function ValidEmail(const EmailAddress: string): Boolean; const EMAIL_REGEX = '^((?>[a-zA-Z\d!#$%&''*+\-/=?^_`{|}~]+\x20*|"((?=[\x01-\x7f])' + '[^"\\]|\\[\x01-\x7f])*"\x20*)*(?<angle><))?((?!\.)' + '(?>\.?[a-zA-Z\d!#$%&''*+\-/=?^_`{|}~]+)+|"((?=[\x01-\x7f])' + '[^"\\]|\\[\x01-\x7f])*")@(((?!-)[a-zA-Z\d\-]+(?<!-)\.)+[a-zA-Z]' + '{2,}|\[(((?(?<!\[)\.)(25[0-5]|2[0-4]\d|[01]?\d?\d))' + '{4}|[a-zA-Z\d\-]*[a-zA-Z\d]:((?=[\x01-\x7f])[^\\\[\]]|\\' + '[\x01-\x7f])+)\])(?(angle)>)$'; var Emails: TStringList; I: SmallInt; // <<<<<< Add this begin Result := True; Emails := TStringList.Create; try Emails.Delimiter := ';'; Emails.StrictDelimiter := True; Emails.DelimitedText := EmailAddress; for I := 0 to Emails.Count - 1 do // <<<<<<<<<<<< Change this.. if not TRegEx.IsMatch(Emails[I], EMAIL_REGEX) then begin Result := False; Break; end; finally Emails.Free; end; // end; No more issue.. This is in D10.4.2. I get the same in D11. :-( Regards and thanks again for the pointer... Ian
  17. Team, Happy New Year to ALL. Given the following example procedure.. procedure TMainForm.SendAPEmails(Sender: TObject); var iRecords: SmallInt; sConsumerEmail, sMsgSubject, sMessage, sManufacturer, sModel, sESN: string; sCompanyName, sContactName, sServiceEmail, sServiceEmailName, sCCEmailAddress: string; MailSender: TELMailSMTPBaseSender; Rslt: TResponse; // const sCannot: string = #13#10 + 'Cannot send AP Emails!'; begin // if Trim(TCompanyInfo.mscStillAPMsgName) = '' then begin MessageBeep(MB_ICONERROR); TaskMessageDlg('Awaiting Parts Message Status!', 'There is no "Still AP Message Name" specified in ... the Company table!' + sCannot, mtError, [mbOK], 0); EXIT; end; // try // LTI1.ShowBalloonHint('AP Emails...', 'Processing of today''s Awaiting Parts emails is commencing.'); // // Check if TCompanyInfo.mscStillAPMsgName is present in the Messages table. Messages.Filtered := False; Messages.Filter := 'MsgName = ' + QuotedStr(TCompanyInfo.mscStillAPMsgName); Messages.Filtered := True; Messages.Open; // if Messages.eof then begin Messages.Close; MessageBeep(MB_ICONERROR); TaskMessageDlg('Awaiting Parts Message Status!', '"Still AP Message Name" ' + TCompanyInfo.mscStillAPMsgName + ' not found in the Messages table!' + sCannot, mtError, [mbOK], 0); EXIT; end; // Messages.Close; // SendAPMsg.ParamByName('BusCode').AsString := TUsersData.msuBusCode; SendAPMsg.ParamByName('iAPUpdateDays').AsInteger := TCompanyInfo.micAPUpdateDays; SendAPMsg.Open; // iRecords := SendAPMsg.RecordCount; // if iRecords = 0 then EXIT; // if iRecords = 1 then sMessage := 'There is one Awaiting Parts Update email to be sent.' else sMessage := 'There are ' + IntToNumberText(iRecords) + ' Awaiting Parts Update emails to be sent.'; // TaskMessageDlg('Awaiting Parts Status!', sMessage, mtInformation, [mbOK], 0); // while not SendAPMsg.eof do begin // sJobNo := SendAPMsg.FieldByName('jobNo').AsString; sConsumerName := Trim(SendAPMsg.FieldByName('ConsumerName').AsString); sConsumerPhone := Trim(SendAPMsg.FieldByName('ConsumerPhoneNo').AsString); sCustomerRef := SendAPMsg.FieldByName('CustomerRef').AsString; sConsumerEmail := Trim(SendAPMsg.FieldByName('ConsumerEmail').AsString); sManufacturer := Trim(SendAPMsg.FieldByName('Manufacturer').AsString); sESN := Trim(SendAPMsg.FieldByName('ESN').AsString); sModel := Trim(SendAPMsg.FieldByName('Model').AsString); // sCompanyName := Trim(SendAPMsg.FieldByName('Name').AsString); sContactName := Trim(SendAPMsg.FieldByName('SvcContactName').AsString); sServiceEmail := Trim(SendAPMsg.FieldByName('ServiceEmail').AsString); sServiceEmailName := Trim(SendAPMsg.FieldByName('ServiceEmailName').AsString); sCCEmailAddress := Trim(SendAPMsg.FieldByName('CCEmailAddress').AsString); // if sConsumerEmail <> '' then begin // // if CheckBlackListEmails(sConsumerEmail) = True then // begin // // // SendAPMsg.Next; // // // Continue; // Do not do the rest of this While loop this time. // // // end; // MailSender := TELMailSMTPClientSender.Create; // try // Copy the current EurekaLog project settings: MailSender.Options := CurrentEurekaLogOptions; // // Set up send method {$IFDEF MailTest} // MailSender := SetMailTestParams(MailSender); // {$ELSE} // // Sender if Trim(TCompanyInfo.mscServiceEmailName) = '' then MailSender.Options.OverrideUserFullName := StrTokenAt(Trim(TCompanyInfo.mscServiceEmail), '@', 1) else MailSender.Options.OverrideUserFullName := Trim(TCompanyInfo.mscServiceEmailName); // MailSender.Options.SendSMTPClientFrom := Trim(TCompanyInfo.mscServiceEmail); // MailSender.Options.SendSMTPClientTarget := sConsumerEmail; // Recipient // {$ENDIF} // MailSender.Options.SendSMTPClientAdditionalHeaders := 'CC: ' + sCCEmailAddress + sCRLF + 'X-Priority: 1' + sCRLF + 'X-MSMail-Priority: Normal' + sCRLF + 'Importance: Normal' + sCRLF; // MailSender.Options.edoUseRealName := False; // MailSender.Options.CustomizedTexts[mtSendDialog_Caption] := 'Sending Awaiting Parts Update email to ' + MailSender.Options.SendSMTPClientTarget + '...'; // // Message Subject sMsgSubject := sCompanyName + '. Awaiting Parts Update advice for Job #: ' + sJobNo + '.'; // MailSender.Options.SendSMTPClientSubject := sMsgSubject; // Subject Text // // Message Body Messages.Filtered := False; Messages.Filter := 'MsgName = ' + QuotedStr(TCompanyInfo.mscStillAPMsgName); Messages.Filtered := True; Messages.Open; // sMessage := MessagesMsgText.AsString; // Messages.Close; // // sMessage variables manually set as Jobtickets is not open att. sMessage := ReplaceText(sMessage, '%JobNo%', sJobNo); sMessage := ReplaceText(sMessage, '%CustomerRef%', sCustomerRef); sMessage := ReplaceText(sMessage, '%CompanyName%', sCompanyName); sMessage := ReplaceText(sMessage, '%ContactName%', TCompanyInfo.mscCoyContactName); sMessage := ReplaceText(sMessage, '%ConsumerName%', sConsumerName); sMessage := ReplaceText(sMessage, '%SvcContactName%', TCompanyInfo.mscCoySvcContactName); sMessage := ReplaceText(sMessage, '%Position%', TCompanyInfo.mscCoySvcPosition); sMessage := ReplaceText(sMessage, '%Manufacturer%', sManufacturer); sMessage := ReplaceText(sMessage, '%IMEI%', sESN); sMessage := ReplaceText(sMessage, '%Model%', sModel); // MailSender.Options.SendSMTPClientMessage := sMessage; // MailSender.Options.SendSMTPClientAppendLogs := False; MailSender.Options.SendSMTPClientUseRealEMail := False; // // For visual dialog during sending: MailSender.ProgressIndicator := ProgressIndicator; FSendProgress := TSendDialogMSClassic.Create(Handle, MailSender.Options); // try // Actual send Rslt := MailSender.SendMessage; // finally FreeAndNil(FSendProgress); end; // if Failed(Ord(Rslt.SendResult)) then begin // LTD1.ExpandedText := Trim(Rslt.ErrorMessage); LTD1.Text := 'Oooops! Sending Awaiting Parts Update email for JT#' + sJobNo + ' failed.' + sCRLF + 'Click the expand button below to view the full error message.' + sCRLF + 'Awaiting Parts Update email sending will now exit.'; LTD1.Execute(Self.Handle); // SendAPMsg.Close; // EmailsLog.Open; EmailsLog.AppendRecord([now, 'AP Update', 'Sending Failed - Customer Awaiting Parts Update email to ' + sConsumerName + ' for Job #: ' + sJobNo + '.', MailSender.Options.SendSMTPClientTarget, TUsersData.msuUserID, StrToInt(sJobNo)]); EmailsLog.Close; // // Exit; // end else begin // {$IF Defined(ELogging) or Defined(Codesite)} LogMessage('Customer Awaiting Parts Update email sent to ' + sConsumerName + ' for Job #: ' + sJobNo + '.'); {$IFEND} // with APJobTickets do begin Open; Edit; FieldByName('DateSent').AsDateTime := now; Post; Close; end; // EmailsLog.Open; EmailsLog.AppendRecord([now, 'AP Update', 'Customer Awaiting Parts Update email sent to ' + sConsumerName + ' for Job #: ' + sJobNo + '.', MailSender.Options.SendSMTPClientTarget, TUsersData.msuUserID, StrToInt(sJobNo)]); EmailsLog.Close; // end; // SendAPMsg.Next; // finally FreeAndNil(MailSender); end; // /// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // end else SendAPMsg.Next; // end; // End While. // LTI1.ShowBalloonHint('AP Emails...', 'Processing of today''s Awaiting Parts emails has completed.'); // finally // SendAPMsg.Close; // end; // end; How do I move/translate that over to a formless Unit please? I have several Print routines similar to this in the Main Form that I would like to put into their own Unit rather than in the Main Form. This is not something I have done before. Regards & TIA, Ian
  18. Ian Branch

    Move a Function or Procedure to a Unit??

    Definitely going this way... Tks.
  19. Ian Branch

    Loss of Datasouce??

    Hi Team, D10.4.2. Revisiting some large projects to update them, I have discovered that DB components have lost either their DataSource and/or their MasterSource. Anybody got any idea why/how this may have happened?? Now I have to go through each DB component, including ttables and tquerys to check their Data/Master Sources.. 😞 Regards & TIA, Ian
  20. Ian Branch

    Loss of Datasouce??

    Hi David, I have been able to do just that, but I am more concerned/interested in how/why it happened so I can take any necessary steps to prevent a repeat. Ian
  21. Ian Branch

    Move a Function or Procedure to a Unit??

    Hi David, That would be a reasonable/accurate statement. I can access the MainForm UI components from the Unit but I was hoping to make the Unit totally self-contained and NOT have any of them on the MainForm. For other reasons, not pertinent to this discussion, my intent can no longer be pursued. 😞 ATT I will be sticking with all the routines/procedures/UI in the MainForm. My thanks to all that have provided suggestions, instruction and guidance. Regards, Ian
  22. Ian Branch

    Move a Function or Procedure to a Unit??

    Hi Stano, That SQL has already been re-done to a single string variable that is then assigned to .SQL.Text. But, I do take your point about the evaluation aspect for future reference. Ian
  23. Ian Branch

    Move a Function or Procedure to a Unit??

    In the new structure - not used by the MainForm at all. Once I have all this sorted there will be 5 or 6 different emailing actions in the Unit called by a single SendEmails procedure in the Unit. The SendEmails Procedure will be called from the MainForm.
  24. Ian Branch

    Move a Function or Procedure to a Unit??

    Hi Mike, sCannot - Interesting. I will look into this. MailSender - Post posting that I moved it to a Unit Var rather than a local. 'With' - I am more than happy to be educated and shown the error of my ways. I think it is more subjective if this is more readable.. procedure CreateAPDataComponents; begin // SendAPMsg := TnlhQuery.Create(nil); // SendAPMsg.DataBaseName := dmC.DBC1.DatabaseName; SendAPMsg.SessionName := dmC.DBC1.SessionName; SendAPMsg.SQL.Text := 'select s.*, j.JobNo, j.CustomerRef, j.ConsumerName, j.ConsumerPhoneNo, j.ConsumerEmail, j.Manufacturer, j.Model, j.ESN, j.ConsumerName, c.Name,'; SendAPMsg.SQL.Text := SendAPMsg.SQL.Text + 'c.ContactName, c.ServiceEmail, c.ServiceEmailName, c.CCEmailAddress, c.SvcContactName from APJobTickets s, JobTickets j, Company c'; SendAPMsg.SQL.Text := SendAPMsg.SQL.Text + 'where (j.buscode = :BusCode) and (j.JobNo = s.JobNo) and (c.BusCode = j.BusCode) and ((Current_Date - Cast(s.DateSent as Date)) >= :iAPUpdateDays) and (Trim(BOTH '' '' from j.ConsumerEmail) <> '''')'; SendAPMsg.SQL.Text := SendAPMsg.SQL.Text + 'order by s.JobNo'; SendAPMsg.ReadOnly := True; // dsSendAPMsg := TDataSource.Create(nil); // dsSendAPMsg.DataSet := SendAPMsg; dsSendAPMsg.AutoEdit := False; // APJobTickets := TnlhTable.Create(nil); // APJobTickets.DataBaseName := dmC.DBC1.DatabaseName; APJobTickets.SessionName := dmC.DBC1.SessionName; APJobTickets.TableName := 'APJobTikets'; APJobTickets.AutoCalcFields := True; APJobTickets.IndexName := 'JobNo'; APJobTickets.MasterSource := dsSendAPMsg; APJobTickets.MasterFields := 'JobNo'; APJobTickets.NullEmptyStrings := True; APJobTickets.RTrimMemos := True; APJobTickets.LTrimStrings := True; // end; We can agree to disagree on readability. 🙂 Ian
  25. Ian Branch

    Move a Function or Procedure to a Unit??

    Hi Mike, Thank you for your feedback. Rather than quoting you each time I will simply respond in order... MessageBeep/TaskDialog - I was not aware of that. Tks. sCannot - Sorry, I don't understand. sCRLF v #13#10 - I am in the process of changing sCRLFs back to #13#10. MailSender - Is declared as a Unit variable and will be created/destroyed by other emailing routines. Is your comment around this still applicable? with APJobTickets - I am aware of the concerns expressed around using with. I figure that as their usage here is in a controlled single action, not nested, there is a word for it but I can't recall it (atomic?), then there should be minimal risk, but improve readability. I think this 'discussion' will last as long as 'with' is in the language. 🙂 Ian
×