Lazarus

Programming => Packages and Libraries => FPSpreadsheet => Topic started by: jollytall on April 04, 2022, 10:18:53 am

Title: Circular reference when insert a row
Post by: jollytall on April 04, 2022, 10:18:53 am
I have a very simple program:
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$mode objfpc}
  4. {$H+}
  5.  
  6. uses
  7.   sysutils,
  8.   fpsTypes,
  9.   fpspreadsheet;
  10.  
  11. var
  12.   WB : TsWorkbook;
  13.   WS : TsWorksheet;
  14. begin
  15. WB := TsWorkbook.Create;
  16. WB.Options := WB.Options + [boAutoCalc];
  17. WS := WB.AddWorksheet('Sheet1');
  18. WS.WriteFormula(WS.GetCell(0,0), '=-A2');
  19. WS.WriteNumber(1, 0, 0);
  20. WS.InsertRow(0);
  21. WB.Free;
  22. end.
  23.  
and the InsertRow crashes with Circular reference.

Instead of =-A2, I tried to use -A2 (I guess it is the same, as = is removed very early in the storing process), =+A2 and +A2 and they all fail. Trying =A2 and A2 work well. For negative I could only make -1*A2 work, but as in my real program I make my much more complicated formulas from many little pieces, it is not an easy option.

I tried to debug the differences between =A2 and =+A2. Both get to unit fpsExprParser, line 2087 (function TsExpressionParser.IterateNodes) but from there the next step is either line 4289 (procedure TsCellExprNode.IterateNodes), the descendant method for the good one or line 2919 (procedure TsExprNode.IterateNodes) the ancestor dummy method. So it seems that FExprnode is not set correctly.
Of course, if AutoCalc is not switched on then the error does not appear until later someone, e.g. in another program tries to use the spreadsheet made here.

What can I do?
Title: Re: Circular reference when insert a row
Post by: wp on April 04, 2022, 11:18:11 am
Please try the new revision that I just committed to CCR. The unary expression node did not implement its own IterateNodes method.

If you don't use svn make the following modifications to fpsexprparser.pas:
Code: Pascal  [Select][+][-]
  1.     procedure IterateNodes(AProc: TsExprNodeProc; AData1, AData2: Pointer;
  2.       var MustRebuildFormulas: boolean); override;
Code: Pascal  [Select][+][-]
  1. procedure TsUnaryOperationExprNode.IterateNodes(AProc: TsExprNodeProc;
  2.   AData1, AData2: Pointer; var MustRebuildFormulas: Boolean);
  3. begin
  4.   FOperand.IterateNodes(AProc, AData1, AData2, MustRebuildFormulas);
  5. end;
Title: Re: Circular reference when insert a row
Post by: jollytall on April 04, 2022, 12:13:31 pm
Thank you. It works!
TinyPortal © 2005-2018