

Ian Branch
Members-
Content Count
1435 -
Joined
-
Last visited
-
Days Won
3
Everything posted by Ian Branch
-
Missing procedures/functions in lookup??
Ian Branch replied to Ian Branch's topic in Delphi IDE and APIs
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.. -
Missing procedures/functions in lookup??
Ian Branch replied to Ian Branch's topic in Delphi IDE and APIs
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 -
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
-
Definitely going this way... Tks.
-
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
-
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
-
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
-
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
-
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.
-
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
-
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
-
Hi Mike, Sure. var APJobTickets: TnlhTable; SendAPMsg: TnlhQuery; dsSendAPMsg: TDataSource; procedure CreateAPDataComponents; begin // SendAPMsg := TnlhQuery.Create(nil); // with SendAPMsg do begin // DataBaseName := dmC.DBC1.DatabaseName; SessionName := dmC.DBC1.SessionName; SQL.Text := 'select s.*, j.JobNo, j.CustomerRef, j.ConsumerName, j.ConsumerPhoneNo, j.ConsumerEmail, j.Manufacturer, j.Model, j.ESN, j.ConsumerName, c.Name,'; SQL.Text := SQL.Text + 'c.ContactName, c.ServiceEmail, c.ServiceEmailName, c.CCEmailAddress, c.SvcContactName from APJobTickets s, JobTickets j, Company c'; SQL.Text := 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) <> '''')'; SQL.Text := SQL.Text + 'order by s.JobNo'; ReadOnly := True; // end; // dsSendAPMsg := TDataSource.Create(nil); // with dsSendAPMsg do begin // DataSet := SendAPMsg; AutoEdit := False; // end; // APJobTickets := TnlhTable.Create(nil); // with APJobTickets do begin // DataBaseName := dmC.DBC1.DatabaseName; SessionName := dmC.DBC1.SessionName; ; TableName := 'APJobTikets'; AutoCalcFields := True; IndexName := 'JobNo'; MasterSource := dsSendAPMsg; MasterFields := 'JobNo'; NullEmptyStrings := True; RTrimMemos := True; LTrimStrings := True; // end; // end; From the above, SendAPMsg, dsSendAPMsg and APJobTickets are used as normal within the SendAPEmails procedure. The components I am creating were only on the MainForm for the SendAPEmails procedure I am now moving to a Unit. Regards, Ian
-
Hi All, I know you are all just dying to know how I am progressing with this.. ;-) Following Mike's suggestions, I firstly made it work without being a TMainForm procedure. This meant referencing the MainForm components in the procedure with the TMainForm. prefix. I then Copied the entire routine and all the Uses, Var and Const clauses over as well into a new Unit just to make sure there were no initial issues. Then there were the components on the MainForm that were being referenced. e.g. tables, queries, dialogs, etc, which needed to be created. I could have left them in the MainForm and just left the TMainForm. references but I don't believe that is the right way to go. I am open to advice/opinions on this. I created the tables and queries in code, all good. I now have to create the remaining MainForm components, dialogs, etc, in code and it should all be good. I have been able to eliminate, through a process of commenting out and seeing what breaks, a significant amount of uses clause entries, as well as some var and const entries. I suspect some of the uses clause entries may have to return as I create the dialogs, etc in code. I have run up against an issue with a third party library which I am pursuing att, all works perfectly in the Form but not in the Unit. The 3rd Party developer is looking into it. Like I said in my first post, this is something new for me. As I work the process I can see other opportunities in other Apps/modules as well however I need to get this right first. :-) I will keep this thread updated as I progress. This may not interest the experienced amongst you but there may be some value to those new to Delphi or like me, new to doing this specifically. At the end of it all I will post the final Unit, as an attachment, for anybody's reference. Regards, Ian
-
Thanks Mike, Your thoughts/insights appreciated. Ian
-
Hi Guys, I'm going around in circles with this. As the title suggests, I want to copy a single record from an ElevateDB TEDBTable to a TkbmMemTable. I have the structure copied using.. kbmMemTable.CreateTableAs(MyTEDBTable, [mtcpoStructure, mtcpoProperties]); But I can't figure how to later copy a single record as desired. kbmMemTable has a CopyRecord function but that only seems to work between two kbmMemTables. :-( A solution would be greatly appreciated. Regards & TIA, Ian
-
Thanks Kim, I actually eliminated the need to copy to the kbmMemTable. I did look at mtCopyRecord but there was no Help Description. I didn't think of looking at mtCopyRecords. My Bad. I will keep this piece of info for any later use. Regards, Ian
-
Rollo62 - One step at a time. 😉 David - Done.
-
Hi Team, Merry Christmas to All. I have ended up with the following... function CopyRecord(tblFrom: TEDBTable; tblTo: TkbmMemTable; const StartIndex: Integer = 0): Boolean; var i: Integer; FieldFrom, FieldTo: TField; begin Result := False; for i := StartIndex to tblFrom.FieldCount - 1 do begin FieldFrom := tblFrom.Fields[i]; FieldTo := tblTo.FindField(FieldFrom.FieldName); if Assigned(FieldTo) then begin FieldTo.Value := FieldFrom.Value; Result := True; end; end; end; Thank you all for your input/suggestions. Regards, Ian
-
wuppdi Welcome Page for Delphi 10.4?
Ian Branch replied to PeterPanettone's topic in Delphi IDE and APIs
Hi @Daniel Is WUPPDI for D11 dead?? -
When was the original GetFieldData deprecated?
Ian Branch posted a topic in RTL and Delphi Object Pascal
I get messages that GetFieldData in the format I am using it is deprecated. That's fine, I can use the overloaded methods. I want to put a conditional in the code so that the overloaded method is used from when it was implemented and the original method prior to that. Does anybody know when the method was deprecated please? Regards & TIA, Ian -
When was the original GetFieldData deprecated?
Ian Branch replied to Ian Branch's topic in RTL and Delphi Object Pascal
Tks Remy. -
Hi Team, Uwe, I had the following code.. {$IFDEF VER140}Variants,{$ENDIF}{Delphi 6} {$IFDEF VER150}Variants,{$ENDIF}{Delphi 7} {$IFDEF VER170}Variants,{$ENDIF}{Delphi 2005} {$IFDEF VER180}Variants,{$ENDIF}{Delphi 2006/7} {$IFDEF VER200}Variants,{$ENDIF}{Delphi 2009} {$IFDEF VER210}Variants,{$ENDIF}{Delphi 2010} {$IFDEF VER220}Variants,{$ENDIF}{Delphi XE} {$IFDEF VER230}Variants,{$ENDIF}{Delphi XE2} {$IFDEF VER240}Variants,{$ENDIF}{Delphi XE3} {$IFDEF VER250}Variants,{$ENDIF}{Delphi XE4} {$IFDEF VER260}Variants,{$ENDIF}{Delphi XE5} {$IFDEF VER270}Variants,{$ENDIF}{Delphi XE6} {$IFDEF VER280}Variants,{$ENDIF}{Delphi XE7} {$IFDEF VER290}Variants,{$ENDIF}{Delphi XE8} {$IFDEF VER300}Variants,{$ENDIF}{Delphi 10 Seattle} {$IFDEF VER310}Variants,{$ENDIF}{Delphi 10.1 Berlin} {$IFDEF VER320}Variants,{$ENDIF}{Delphi 10.2 Tokyo} {$IFDEF VER330}Variants,{$ENDIF}{Delphi 10.3 Rio} {$IFDEF VER340}Variants, System.UITypes, VCL.FileCtrl,{$ENDIF}{Delphi 10.4 Sydney} {$IFDEF VER350}Variants, System.UITypes, VCL.FileCtrl,{$ENDIF}{Delphi 11} I applied UsesCleaner.exe and got the following.. Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, Vcl.Buttons, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.DBCtrls, Vcl.DBLogDlg, Vcl.Printers, * {Delphi 6}, * {Delphi 7}, * {Delphi 2005}, * {Delphi 2006/7}, * {Delphi 2009}, * {Delphi 2010}, * {Delphi XE}, * {Delphi XE2}, * {Delphi XE3}, * {Delphi XE4}, * {Delphi XE5}, * {Delphi XE6}, * {Delphi XE7}, * {Delphi XE8}, * {Delphi 10 Seattle}, * {Delphi 10.1 Berlin}, * {Delphi 10.2 Tokyo}, * {Delphi 10.3 Rio}, * {Delphi 10.4 Sydney}, * {Delphi 11} Is there any chance of this being addressed?? Regards & TIA, Ian
-
All very messy when it could have been so easy.... :-(
-
Tks Uwe, In my case it also seems to be related to the presence/need for VclTee.TeeGDIPlus because there is an actual graph on the form. In other units there is no graph and the CompilerVersion conditionals are quite happy. Ian
-
Hi Team, So, playing with the CompilerVersion I get some strange results. Starting with this.. {$IFDEF VER130}TeeProcs, TeEngine, Chart, Series;{$ENDIF}{Delphi 5} {$IFDEF VER140}TeeProcs, TeEngine, Chart, Series;{$ENDIF}{Delphi 6} {$IFDEF VER150}TeeProcs, TeEngine, Chart, Series;{$ENDIF}{Delphi 7} {$IFDEF VER170}TeeProcs, TeEngine, Chart, Series;{$ENDIF}{Delphi 2005} {$IFDEF VER180}TeeProcs, TeEngine, Chart, Series;{$ENDIF}{Delphi 2006/7} {$IFDEF VER200}TeeProcs, TeEngine, Chart, Series;{$ENDIF}{Delphi 2009} {$IFDEF VER210}TeeProcs, TeEngine, Chart, Series;{$ENDIF}{Delphi 2010} {$IFDEF VER220}TeeProcs, TeEngine, Chart, Series;{$ENDIF}{Delphi XE} {$IFDEF VER230}TeeProcs, TeEngine, Chart, Series;{$ENDIF}{Delphi XE2} {$IFDEF VER240}VCLTee.TeeProcs, VCLTee.TeEngine, VCLTee.Chart, VCLTee.Series;{$ENDIF}{Delphi XE3} {$IFDEF VER250}VCLTee.TeeProcs, VCLTee.TeEngine, VCLTee.Chart, VCLTee.Series;{$ENDIF}{Delphi XE4} {$IFDEF VER260}VCLTee.TeeProcs, VCLTee.TeEngine, VCLTee.Chart, VCLTee.Series;{$ENDIF}{Delphi XE5} {$IFDEF VER270}VCLTee.TeeProcs, VCLTee.TeEngine, VCLTee.Chart, VCLTee.Series;{$ENDIF}{Delphi XE6} {$IFDEF VER280}VCLTee.TeeProcs, VCLTee.TeEngine, VCLTee.Chart, VCLTee.Series;{$ENDIF}{Delphi XE7} {$IFDEF VER290}VCLTee.TeeProcs, VCLTee.TeEngine, VCLTee.Chart, VCLTee.Series;{$ENDIF}{Delphi XE8} {$IFDEF VER300}VCLTee.TeeProcs, VCLTee.TeEngine, VCLTee.Chart, VCLTee.Series;{$ENDIF}{Delphi 10 Seattle} {$IFDEF VER310}VCLTee.TeeProcs, VCLTee.TeEngine, VCLTee.Chart, VCLTee.Series;{$ENDIF}{Delphi 10.1 Berlin} {$IFDEF VER320}VCLTee.TeeProcs, VCLTee.TeEngine, VCLTee.Chart, VCLTee.Series;{$ENDIF}{Delphi 10.2 Tokyo} {$IFDEF VER330}VCLTee.TeeProcs, VCLTee.TeEngine, VCLTee.Chart, VCLTee.Series, VclTee.TeeGDIPlus;{$ENDIF}{Delphi 10.3 Rio} {$IFDEF VER340}VCLTee.TeeProcs, VCLTee.TeEngine, VCLTee.Chart, VCLTee.Series;{$ENDIF}{Delphi 10.4 Sydney} {$IFDEF VER350}VCLTee.TeeProcs, VCLTee.TeEngine, VCLTee.Chart, VCLTee.Series;{$ENDIF}{Delphi 11} This works fine in D10.4.2 & D11. Implementing the CompilerVersion idea.. In D11 - At design time this is quite happy.. {code} uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, Menus, printers, {$IF (CompilerVersion >= 13.0) and (CompilerVersion <= 23.0)}TeeProcs, TeEngine, Chart, Series;{$ENDIF} {$IF CompilerVersion >= 24.0}VCLTee.TeEngine, VCLTee.Series, VCLTee.TeeProcs, VCLTee.Chart, VclTee.TeeGDIPlus;{$ENDIF} {code} When I build the app it does this and of course errors.. {code} uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, Menus, printers, VclTee.TeeGDIPlus, VCLTee.TeEngine, VCLTee.Series, VCLTee.TeeProcs, VCLTee.Chart, {$IF (CompilerVersion >= 13.0) and (CompilerVersion <= 23.0)}TeeProcs, TeEngine, Chart, Series;{$ENDIF} {$IF CompilerVersion >= 24.0}VCLTee.TeEngine, VCLTee.Series, VCLTee.TeeProcs, VCLTee.Chart, VclTee.TeeGDIPlus;{$ENDIF} {code} It is obviously happy at build time with the "{$IF (CompilerVersion >= 13.0) and (CompilerVersion <= 23.0)}TeeProcs, TeEngine, Chart, Series;{$ENDIF}" line. I don't understand what its problem is with the second line.. I get similar but not the same results in D10.4.2. Is this a bug?? Ian