Recent

Author Topic: Circular reference when insert a row  (Read 822 times)

jollytall

  • Sr. Member
  • ****
  • Posts: 306
Circular reference when insert a row
« 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?

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: Circular reference when insert a row
« Reply #1 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:
  • In the interface part of the unit add this line to the public section of class TsUnaryOperationExprNode:
Code: Pascal  [Select][+][-]
  1.     procedure IterateNodes(AProc: TsExprNodeProc; AData1, AData2: Pointer;
  2.       var MustRebuildFormulas: boolean); override;
  • In the implementation part of the unit add this code:
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;
« Last Edit: April 04, 2022, 11:24:55 am by wp »

jollytall

  • Sr. Member
  • ****
  • Posts: 306
Re: Circular reference when insert a row
« Reply #2 on: April 04, 2022, 12:13:31 pm »
Thank you. It works!

 

TinyPortal © 2005-2018