Ian Branch
Members-
Content Count
1352 -
Joined
-
Last visited
-
Days Won
3
Everything posted by Ian Branch
-
Hi Team, D11. I am playing with TFDMemTable. I have the following line of code... FDMemTable1.CopyDataSet(Company, [coStructure, coAppend]); Company is previously filtered so there is only one record 'visible'. How can I tell how much memory has been used as a result of just this code/action please? Regards & TIA, Ian
-
Hi Team, I am cleaning up some exception handling in some old code. The code goes something like the following.. if E:ErrorCode = xx then doshomething else if E:ErrorCode = yy then dosomethingelse ... .. else TaskMessageDlg('Errormessage!', E.Message, mtError, [mbOK], 0); If using MadExcept or EurekaLog, is the following proper/acceptable?? if E:ErrorCode = xx then doshomething else if E:ErrorCode = yy then dosomethingelse ... .. else raise; to let MadExcept or EurekaLog process the unhandled exception(s)?? Regards & TIA, Ian
-
So. The short answer is No. Raise has to be within the exception block. That was all I need to know. What I can do is replace this.. else TaskMessageDlg('Errormessage!', E.Message, mtError, [mbOK], 0); end; // end else TaskMessageDlg('Error message!', E.Message, mtError, [mbOK], 0); // end; with this.. else Action := daFail; end; // end else Action := daFail; // end; The solution I was ultimately after. Thank you for your contributions. Ian
-
Hi Team, I do appreciate your inputs. I thought I was keeping it simple and asking a simple question... Oh well. OK. Here is the full code sequence....Users is a TTable. procedure TMainForm.UsersEditError(DataSet: TDataSet; E: EDatabaseError; var Action: TDataAction); begin // _EditError(Action, E, DataSet); // end; procedure TMainForm._EditError(out Action: TDataAction; E: EDatabaseError; DataSet: TDataSet); var sMessage: string; begin // sMessage := 'The record you are trying to edit in the ' + DataSet.Name + ' table '; // Action := daAbort; // if (E is EEDBError) then begin // case EEDBError(E).ErrorCode of EDB_ERROR_LOCKROW: if TaskMessageDlg('Locked record!', sMessage + ' is currently locked, do you want to try to edit this record again?', mtWarning, [mbYes, mbNo], 0) = mrYes then Action := daRetry; EDB_ERROR_ROWDELETED: begin TaskMessageDlg('Deleted record!', sMessage + ' has been deleted since it was last retrieved', mtError, [mbOK], 0); DataSet.Refresh; end; EDB_ERROR_ROWMODIFIED: begin TaskMessageDlg('Modified record!', sMessage + ' has been modified since it was last retrieved, the record will now be refreshed', mtWarning, [mbOK], 0); DataSet.Refresh; Action := daRetry; end; else TaskMessageDlg('Errormessage!', E.Message, mtError, [mbOK], 0); end; // end else TaskMessageDlg('Error message!', E.Message, mtError, [mbOK], 0); // end; Why have I gone this route? This way I can use one _EditError procedure for all TTable or TQuery EditErrors. My basic question is - Is it safe/correct/appropriate to replace the last two 'TaskMessageDlg(...' with 'raise;' to pass whatever the unhandled exception is to MadExcept or EurekaLog? Regards, Ian
-
Hi joaodanet2018, Thank you for your input. My example above was extremely simplified and was specifically enquiring if the use of raise in this context was correct. The actual code is handling the common issues and giving the User an opportunity to correct their mistakes, however there are always the exceptions, pun intended, that aren't accounted for. MadExcept & EurekaLog allow you to capture details of this exceptions and look at root cause with the objective of eliminating or mitigating them. Ian
-
Hi Team, Let's say I have two units in the App. Unit1 & Unit 2 where Unit1 is the main unit and Unit2 is a datamodule with a ttable, MyTable, on it. Is it possible to create an alias for the datamodule/ttable? i.e. instead of having to type 'Unit2.Mytable.FieldByName......' when calling it from Unit1, instead, something like 'U2MT.FieldByName.....'? Would save a hell of a lot of typing... :-) Or, is there an alternative?? Whilst I have been specific here in regards to the units/components, I can see additional usage if the ability exists. Regards & TIA, Ian
-
Hi Pat, Ahhh. Now I see/understand. Thank you for the clarification. Much Appreciated. Thank you to all contributors. So, there is no such thing as a freebee. What, if any, is the penalty for this construct? Regards, Ian
-
Hi All, Sorry, you are doing things that are over my head. 😞 I'm sure what you are telling me is quite correct, but I'm afraid I don't understand how to apply them to my scenario. That is my knowledge deficiency. I really would appreciate it if you could explain in terms of my Unit1/Unit2/TTable example. Then perhaps I can relate it to what you have above and reach an understanding. Regards, Ian
-
Ah Ha! Excellent. Thank you.
-
Hi Team, Given the following TTable.EditError(DataSet:TDataSet; E: EDatabaseError; var Action: TDataAction); If I now feed the parameters to a second procedure via.. _EditError(Action, E, DataSet); Given that _EditError is defined as.. procedure _EditError(out Action: TDataAction; E: EDatabaseError; DataSet: TDataSet); And in _EditError, Action may be set to daRetry or daAbort.. Will the Action be passed back up to the TTable.EditError or do I need to make the 'out Action: TDataAction;' in the _EditError definition a var?? Regards & TIA, Ian
-
Maybe they are updating it for Delphi 11.1?? Says he with a hopeful thought...
-
wuppdi Welcome Page for Delphi 10.4?
Ian Branch replied to PeterPanettone's topic in Delphi IDE and APIs
@Daniel In this case silence is not golden... 😞 -
Hi Team, D10.4.2, Indy as distributed with D10.4.2. I implemented this code many moons ago and it was working fine. It may have been with Indy10 via GitHub. // HTTP := TIdHTTP.Create; try try interim := HTTP.Get('http://quotes4all.net'); // ChopStart := pos(StartQuote, interim); // if ChopStart > 1 then begin // ChopEnd := PosEx(EndQuote, interim, ChopStart + 1); // if ChopEnd > ChopStart then begin // interim := Copy(interim, ChopStart, ChopEnd - ChopStart); InCmnd := False; for Cntr := 1 to Length(interim) do begin if interim[Cntr] = '<' then InCmnd := True else if interim[Cntr] = '>' then InCmnd := False else if not InCmnd then Quote := Quote + interim[Cntr]; end; // TaskMessageDlg('Thought for the Day...', Quote, mtInformation, [mbOK], 0); // end; end; finally FreeAndNil(HTTP); // .Free; lThoughtForTheDay := True; end; // except on E: Exception do begin if E.ClassName = 'EIdConnClosedGracefully' then begin // ShowMessage('Unable to access Thought for the Day at this time.'); // EXIT; end else begin // ShowMessage('Exception class name = ' + E.ClassName); ShowMessage('Exception message = ' + E.message); // end; end; // end At a time not that long ago I had to reinstall everything. !@#$%^& Windows.. Before I go through the pain of removing the distributed Indy and re-installing Indy10, is this my issue? This doesn't work under the distributed Indy?? Regards & TIA, Ian
-
Dave - Oh so true. Thanks Remy, Yes that now works. But, I have to consider, it has been not working for X time and no User has reported/mentioned it, which suggests they don't really care for it. I prefer to get rid of code if isn't being used or provides no value. I will ponder my navel for a bit and probably end up removing the functionality. Having said that, I am glad it is working again. 🙂 Regards & Tks, Ian
-
Apologies Remy, My head has been elsewhere with other more pressing operational issues. :-( I have since discovered by examining 'interim' that the page structure in http://quotes4all.net has changed. That is why the routine is no longer working. FYI - const StartQuote = '<span class="quote">'; EndQuote = '</span>'; The functionality was a nice to have, dare I say a novelty piece, so no loss if I take it away. Apologies for wasting your time. Regards, Ian
-
Hi Team, I have the following construct.. unit CompanyData; interface { mlXX = memory logical - Boolean miXX = memory integer = Integer msXX = memory string = String mXuXX = User data. mXcXX = Company data. } type TCompanyData = class class var // mscRecordEditInsertMessage: string; // mlcApplicationGlobalEmails: Boolean; // mlcSendSurveyEmails: Boolean; micSendSurveyDays: Integer; mlcPartsBinNoCompulsory: Boolean; mlcSendAPEmails: Boolean; micAPUpdateDays: SmallInt; micACUpdateDays: SmallInt; micACUpdateLimit: SmallInt; mlcSendDailyReportEmails: Boolean; mlcSendWeeklyReportEmails: Boolean; mlcSendMonthlyReportEmails: Boolean; mscSurveysEmailAddress: string; mscStillAPMsgName: string; mscStillACMessageName: string; ... ... end; Each variable represents a field in the Company TTable. Is there a simple mechanism in Delphi by which I can populate these variables directly from the TTable? Or, do I have to iterate through the fields and assign the value of each field to the variable?? If I have to iterate, is it best to do that in the Class Constructor?? i.e. Something like.. ... ... ... // class constructor Create; // end; /// ///////////////////////////////////////////////////////////////////////////////// implementation class constructor TCompanyData.Create; var i: smallint; begin // For i = 0 to Company.FieldCount do begin TCompanyData[i].AsVariant := Company.Fields[i].AsVariant; Next i; end; // end; Regards & TIA, Ian
-
Thanks FredS
-
Hi Remy, Thank you for your feedback. I found the code over 18 months ago, implemented it as is and it worked fine. I have had no reason to re-visit it until now when I discovered it wasn't working. What it used to do is scrape a thought for the day from the indicated web site and display it in the TaskMessageDialog to the User. After your comments, this is now the full function code but it still doesn't retrieve a Thought for the Day. 😞 function OnAfterShow: Boolean; var HTTP: TIdHTTP; Quote: string; interim: string; ChopStart: Integer; ChopEnd: Integer; InCmnd: Boolean; Cntr: Integer; begin // Result := True; // if MainForm.DBWReg.ReadBool('ThoughtForTheDay', 'ShowAtStart', True) then begin // try HTTP := TIdHTTP.Create; try interim := HTTP.Get('http://quotes4all.net'); // ChopStart := pos(StartQuote, interim); if ChopStart > 1 then begin ChopEnd := PosEx(EndQuote, interim, ChopStart + 1); if ChopEnd > ChopStart then begin interim := Copy(interim, ChopStart, ChopEnd - ChopStart); InCmnd := False; for Cntr := 1 to Length(interim) do begin if interim[Cntr] = '<' then InCmnd := True else if interim[Cntr] = '>' then InCmnd := False else if not InCmnd then Quote := Quote + interim[Cntr]; end; TaskMessageDlg('Thought for the Day...', Quote, mtError, [mbOK], 0); end; end; finally FreeAndNil(HTTP); // .Free; end; // except // on E: EIdConnClosedGracefully do begin // ShowMessage('Unable to access Thought for the Day at this time.'); // EXIT; end; on E: Exception do begin // ShowMessage('Exception class name = ' + E.ClassName); ShowMessage('Exception message = ' + E.message); // end; // end; // end; // end; It is of course not impossible that http://quotes4all.net has changed and therefore the code is no longer applicable. I don't know. I am more than open to any alternative means to the same end. Can you point me to some appropriate code/example?? Regards & TIA, Ian
-
Hi Uwe, Something changed under-the-hood from D10.4 to D11. All working fine now in both D10.4 & D11. Thanks for the quick fix. Regards, Ian
-
Hi Uwe, Yes, there could be a field with a Null. I made the change. I still get an " Invalid class typecast." error and this.. To validate your theory I put some text into the Null field. Now it works fine, with and without the code change. Does the handling of Null need to be elsewhere?? There are other NULL fields in the record but they don't seem to affect it. With a Null in the field it works fine in D10.4.2 but not D11. Update - I changes this code.. procedure TDataSetHelper.TDataSetRecord<T>.TFieldMapping.LoadFromField(var Target: T); begin FRTTIField.SetValue(GetPointer(Target), TValue.FromVariant(FField.Value)); end; To this.. procedure TDataSetHelper.TDataSetRecord<T>.TFieldMapping.LoadFromField(var Target: T); var val: TValue; begin if FField.IsNull then val := TValue.Empty else val := TValue.FromVariant(FField.Value); FRTTIField.SetValue(GetPointer(Target), val); end; And it seems to be working. I will do some more testing tomorrow and advise. Regards, Ian
-
Hi Team, Is there a way to make formatting for a section of code stick rather than being reformatted by the Formatter?? e.g. Keep this... result := Function(param1, param2, param3, param4); Rather than doing this.. result := Function(param1, param2, param3, param4); When the Formatter is invoked... I'd like to do this for clarity/readability. Regards & TIA, Ian
-
Make Formatting stick for a section of code.?
Ian Branch replied to Ian Branch's topic in Delphi IDE and APIs
Tks Thomas. -
Hi @Uwe Raabe Just came across an issue. The DataSetHelper LoadFromField works fine with my Data in D10.4.2. Unfortunately I am getting an " Invalid class typecast." error for the same code/data in D11 at line 454. It is happening on a couple of Apps. This may be an ANSI v UniCode issue that I haven't correctly set in D11 as yet but I thought I would give you a heads-up. I have not embraced UniCode as my main Customers are still on Win 7 32Bit. :-( Regards, Ian
-
Hi Team, I need to be able to detect and return true or false, if an integer number is in a delimited string of numbers.. i.e. If the integer is say 47, and the delimited number string is '12;94;128;3;127,147', then it would return False. If the integer is say 47, and the delimited number string is '12;94;128;3;127,47', then it would return True. If the integer is say 47, and the delimited number string is '12;147;128;3;127,47', then it would return True. Your thoughts/suggestions appreciated. Regards & TIA, Ian
-
Hi Team, Thank you for your further suggestions. I am now going with Uwe's suggestion. Uwe - I like simple. 0x9000FFFF - regular expressions scare me, like pointers... ;-) Atilla - Thank you for the pointers. Regards & Tks again, Ian