home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 January / Chip_2003-01_cd1.bin / zkuste / delphi / kolekce / d567 / FLEXCEL.ZIP / XLSAdapter / UXlsFormula.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2002-09-26  |  8.3 KB  |  302 lines

  1. unit UXlsFormula;
  2.  
  3. interface
  4. uses
  5.   {$IFDEF ConditionalExpressions}{$if CompilerVersion >= 14} variants,{$IFEND}{$ENDIF} //Delphi 6 or above
  6.   Classes, SysUtils, UXlsBaseRecords, XlsMessages, UXlsTokenArray;
  7.  
  8. type
  9.   TFormulaRecord = class(TCellRecord)
  10.   private
  11.     FormulaValue: variant;
  12.  
  13.     procedure ArrangeTokensInsertRows(const InsPos, InsOffset, CopyOffset: integer; const SheetInfo: TSheetInfo);
  14.     procedure ArrangeSharedTokens;
  15.   public
  16.     constructor Create(const aId: word; const aData: PArrayOfByte; const aDataSize: integer);override;
  17.     procedure ArrangeInsert(const aPos, aCount:integer;  const SheetInfo: TSheetInfo);override;
  18.     procedure ArrangeCopy(const NewRow: Word);override;
  19.     procedure SaveToStream(const Workbook: TStream); override;
  20.  
  21.     function IsExp(var Key: Cardinal): boolean;
  22.     procedure MixShared(const PData: PArrayOfByte; const aDataSize: integer);
  23.     function GetValue: Variant; override;
  24.     procedure SetFormulaValue(const v: variant);
  25.   end;
  26.  
  27.   TNameRecord =  class (TBaseRecord)
  28.   private
  29.     procedure ArrangeTokensInsertRows(const InsPos, InsOffset, CopyOffset: integer; const SheetInfo: TSheetInfo);
  30.     function NameLength: byte;
  31.     function NameSize: integer;
  32.     function OptionFlags: byte;
  33.   public
  34.     constructor Create(const aId: word; const aData: PArrayOfByte; const aDataSize: integer);override;
  35.     procedure ArrangeInsert(aPos, aCount:integer; const SheetInfo: TSheetInfo);
  36.     procedure ArrangeInsertSheets(const FirstSheet, SheetCount: Word);
  37.  
  38.     function ArrangeCopySheet(const SheetInfo: TSheetInfo): TNameRecord;
  39.  
  40.     function RangeSheet: integer;
  41.     function RefersToSheet(const GetSheet:TGetSheet) : integer;
  42.     function Name:Widestring;
  43.     function R1: integer;
  44.     function R2: integer;
  45.     function C1: integer;
  46.     function C2: integer;
  47.   end;
  48.  
  49.   TShrFmlaRecord=class(TBaseRecord)
  50.   public
  51.     function FirstRow: integer;
  52.     function LastRow: integer;
  53.     function FirstCol: integer;
  54.     function LastCol: integer;
  55.     function Key: Cardinal;
  56.   end;
  57.  
  58. implementation
  59.  
  60.  
  61. { TFormulaRecord }
  62.  
  63. procedure TFormulaRecord.ArrangeInsert(const aPos, aCount:integer; const SheetInfo: TSheetInfo);
  64. begin
  65.   inherited;
  66.   ArrangeTokensInsertRows(aPos, aCount, 0, SheetInfo);
  67. end;
  68.  
  69. constructor TFormulaRecord.Create(const aId: word;
  70.   const aData: PArrayOfByte; const aDataSize: integer);
  71. var
  72.   d: double;
  73. begin
  74.   inherited;
  75.   //Save the formula result
  76.   FormulaValue:=unassigned;
  77.   if GetWord(Data,12)<> $FFFF then //it's a number
  78.   begin
  79.     move(Data[6], d, sizeof(d));
  80.     FormulaValue:=d;
  81.   end else
  82.   begin
  83.     case Data[6] of
  84.       0: FormulaValue:=''; //It's a string. We will fill it later when we read the string record
  85.       1: FormulaValue:=data[8]=1; //boolean
  86.       //2 is error. we can't codify this on a variant.
  87.     end; //case
  88.   end;
  89.  
  90.   FillChar(Data^[6],8,0); //clear result
  91.   Data^[6]:=2; //error value
  92.   SetWord(Data,12,$FFFF);
  93.   FillChar(Data^[16],4,0); //clear chn
  94.  
  95.   // For automatic recalc...Data^[14]:=Data^[14] or 2;
  96. end;
  97.  
  98. procedure TFormulaRecord.ArrangeCopy(const NewRow: Word);
  99. const
  100.   SheetInfo: TSheetInfo=(InsSheet:-1;FormulaSheet:-1;GetSheet:nil;SetSheet:nil);
  101. begin
  102.   ArrangeTokensInsertRows( 0, 0, NewRow-Row, SheetInfo); //Sheet info doesn't have meaninig on copy
  103.   inherited;   //should be last, so we dont modify Row
  104. end;
  105.  
  106. procedure TFormulaRecord.ArrangeTokensInsertRows(const InsPos, InsOffset,
  107.   CopyOffset: integer; const SheetInfo: TSheetInfo);
  108. begin
  109.   try
  110.     UXlsTokenArray.ArrangeInsertRows(Data, 22, 22+GetWord(Data,20), InsPos, InsOffset, CopyOffset, SheetInfo);
  111.   except
  112.     on e: ETokenException do raise Exception.CreateFmt(ErrBadFormula,[ Row+1, Column+1, e.Token]);
  113.     else raise;
  114.   end; //Except
  115. end;
  116.  
  117. procedure TFormulaRecord.ArrangeSharedTokens;
  118. begin
  119.   try
  120.     UXlsTokenArray.ArrangeSharedFormulas(Data, 22, 22+GetWord(Data,20), Row, Column);
  121.   except
  122.     on e: ETokenException do raise Exception.CreateFmt(ErrBadFormula,[ Row+1, Column+1, e.Token]);
  123.     else raise;
  124.   end; //Except
  125. end;
  126.  
  127. function TFormulaRecord.IsExp(var Key: Cardinal): boolean;
  128. begin
  129.   Result:= (DataSize=27) and (GetWord(Data,20)=5) and (Data[22]=1);
  130.   if Result then Key:=GetWord(Data,23) or (GetWord(Data,25) shl 16);
  131. end;
  132.  
  133. procedure TFormulaRecord.MixShared(const PData: PArrayOfByte; const aDataSize: integer);
  134. var
  135.   NewDataSize: integer;
  136. begin
  137.   //Important: This method changes the size of the record without notifying it's parent list
  138.   //It's necessary to adapt the Totalsize in the parent list.
  139.   NewDataSize:=DataSize - 5+ aDataSize-8 ;
  140.   ReallocMem(Data, NewDataSize);
  141.   //Now is safe to change DataSize
  142.   DataSize:=NewDataSize;
  143.   Move(PData[8], Data[20], aDataSize-8);
  144.   ArrangeSharedTokens;
  145. end;
  146.  
  147. function TFormulaRecord.GetValue: Variant;
  148. begin
  149.   Result:=FormulaValue;
  150. end;
  151.  
  152. procedure TFormulaRecord.SaveToStream(const Workbook: TStream);
  153. begin
  154.   inherited;
  155. end;
  156.  
  157. procedure TFormulaRecord.SetFormulaValue(const v: variant);
  158. begin
  159.   FormulaValue:=v;
  160. end;
  161.  
  162. { TNameRecord }
  163.  
  164. procedure TNameRecord.ArrangeInsertSheets(const FirstSheet, SheetCount: Word);
  165. begin
  166.   if (RangeSheet<>$FFFF) and (RangeSheet>=FirstSheet) then IncWord(Data, 8, SheetCount, MaxSheets+1); //NewSheet is 0 based, Data[8] is one-based;
  167. end;
  168.  
  169. procedure TNameRecord.ArrangeTokensInsertRows(const InsPos, InsOffset,
  170.   CopyOffset: integer; const SheetInfo: TSheetInfo);
  171. begin
  172.   try
  173.     UXlsTokenArray.ArrangeInsertRows(Data, 14+ NameSize,14+ NameSize+GetWord(Data,4), InsPos, InsOffset, CopyOffset, SheetInfo);
  174.   except
  175.     on e: ETokenException do raise Exception.CreateFmt(ErrBadName,[ Name, e.Token]);
  176.     else raise;
  177.   end; //Except
  178. end;
  179.  
  180. constructor TNameRecord.Create(const aId: word; const aData: PArrayOfByte;
  181.   const aDataSize: integer);
  182. begin
  183.   inherited;
  184.  
  185. end;
  186.  
  187. procedure TNameRecord.ArrangeInsert(aPos, aCount: integer; const SheetInfo: TSheetInfo);
  188. begin
  189.   ArrangeTokensInsertRows( aPos, aCount, 0, SheetInfo);
  190. end;
  191.  
  192. function TNameRecord.Name: Widestring;
  193. var
  194.   s: string;
  195. begin
  196.   if (OptionFlags and 1)=1 then
  197.   begin
  198.     SetLength(Result, NameLength);
  199.     Move(Data[15], Result[1], NameLength*2);
  200.   end else
  201.   begin
  202.     SetLength(s, NameLength);
  203.     Move(Data[15], s[1], NameLength);
  204.     Result:=s;
  205.   end;
  206. end;
  207.  
  208. function TNameRecord.NameLength: byte;
  209. begin
  210.   Result:= Data[3];
  211. end;
  212.  
  213. function TNameRecord.NameSize: integer;
  214. begin
  215.   Result:= GetStrLen(false , Data, 14, true, NameLength);
  216. end;
  217.  
  218. function TNameRecord.OptionFlags: byte;
  219. begin
  220.   OptionFlags:= Data[14];
  221. end;
  222.  
  223. function TNameRecord.RangeSheet: integer;
  224. begin
  225.   Result:=GetWord(Data,8)-1;
  226. end;
  227.  
  228. function TNameRecord.ArrangeCopySheet(const SheetInfo: TSheetInfo): TNameRecord;
  229. begin
  230.   try
  231.     UXlsTokenArray.ArrangeInsertSheets(Data, 14+ NameSize,14+ NameSize+GetWord(Data,4), SheetInfo);
  232.   except
  233.     on e: ETokenException do raise Exception.CreateFmt(ErrBadName,[ Name, e.Token]);
  234.     else raise;
  235.   end; //Except
  236.  
  237.   SetWord(Data, 8, SheetInfo.InsSheet+1); //InsSheet is 0 based, Data[8] is one-based;
  238.   Result:=Self;
  239. end;
  240.  
  241. function TNameRecord.R1: integer;
  242. begin
  243.   if Data[14+ NameSize] in tk_Area3d then Result:= GetWord(Data, 15+2+NameSize)
  244.   else Result:=-1;
  245. end;
  246.  
  247. function TNameRecord.R2: integer;
  248. begin
  249.   if Data[14+ NameSize] in tk_Area3d then Result:= GetWord(Data, 15+4+NameSize)
  250.   else Result:=-1;
  251. end;
  252.  
  253. function TNameRecord.RefersToSheet(const GetSheet:TGetSheet): integer;
  254. begin
  255.   if Data[14+ NameSize] in tk_Area3d then Result:= GetSheet(GetWord(Data, 15+NameSize))
  256.   else Result:=-1;
  257. end;
  258.  
  259.  
  260. function TNameRecord.C1: integer;
  261. begin
  262.   if Data[14+ NameSize] in tk_Area3d then Result:= GetWord(Data, 15+6+NameSize)
  263.   else Result:=-1;
  264. end;
  265.  
  266. function TNameRecord.C2: integer;
  267. begin
  268.   if Data[14+ NameSize] in tk_Area3d then Result:= GetWord(Data, 15+8+NameSize)
  269.   else Result:=-1;
  270. end;
  271.  
  272.  
  273. { TShrFmlaRecord }
  274. function TShrFmlaRecord.FirstRow: integer;
  275. begin
  276.   Result:=GetWord(Data,0);
  277. end;
  278.  
  279. function TShrFmlaRecord.LastRow: integer;
  280. begin
  281.   Result:=GetWord(Data,2);
  282. end;
  283.  
  284. function TShrFmlaRecord.FirstCol: integer;
  285. begin
  286.   Result:=Data[4];
  287. end;
  288.  
  289. function TShrFmlaRecord.LastCol: integer;
  290. begin
  291.   Result:=Data[5];
  292. end;
  293.  
  294. function TShrFmlaRecord.Key: cardinal;
  295. begin
  296.   Result:=GetWord(Data,0) or Data[4] shl 16;
  297. end;
  298.  
  299.  
  300. end.
  301.  
  302.