Converting VARIANTs and FASTREPORT 6

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

Post Reply
kingbarsa
Posts: 5
Joined: Tue Oct 20, 2020 7:06 am

Converting VARIANTs and FASTREPORT 6

Post by kingbarsa »

Hi All

Extending from previous post involving colors in StringGrids, I am now grappling with applying colors to FastReports (but only in reference to run-time built reports with Arrays). Im fine with setting the color for fixed format report where the Memo Variable has a unique name.

That I did like this

Code: Select all

	TfrxMemoView * CallStabMemo1 = dynamic_cast <TfrxMemoView *> (frxReport1->FindObject("MemoStabPassFail1"));
	if (GZForm->MaxGzValue->Caption.ToDouble()<0.20)
	  CallStabMemo1->Font->Color = clRed;
	else
	  CallStabMemo1->Font->Color = clBlack;
However where the Memo's or my my case cells, are defined via an Array Dataset, the Memo Variable Names are not unique.

See extract from a FR3 file. You will have to scroll a long way to the right to see the Memo Variable Names.

Hence say I wanted to change the colour of one particular [FSM0], but at run time there might be 12 [FSM0]'s from an array of 12 lines, so I dont have a unique Variable Name to catch hold of.

Code: Select all

    </TfrxDetailData>
    <TfrxSubdetailData Name="" FillType="ftBrush" FillGap.Top="0" FillGap.Left="0" FillGap.Bottom="0" FillGap.Right="0" Frame.Typ="0" Height="17.0078843379581" Left="0" Top="230.551305506535" Width="718.110691070557" ColumnWidth="0" ColumnGap="0" DataSet="dsArray0" DataSetName="dsArray0" RowCount="0">
      <TfrxMemoView Name="Memo29" AllowVectorExport="true" Left="15.1181198120117" Top="0" Width="188.976497650146" Height="17.0078843379581" Font.Charset="1" Font.Color="0" Font.Height="-11" Font.Name="Arial" Font.Style="0" Frame.Typ="15" Frame.Width="0.5" ParentFont="false" Text="[TankName0]"/>
      <TfrxMemoView Name="Memo30" AllowVectorExport="true" Left="204.094621066599" Top="0" Width="52.9134184409309" Height="17.0078843379581" Font.Charset="1" Font.Color="0" Font.Height="-11" Font.Name="Arial" Font.Style="0" Frame.Typ="15" Frame.Width="0.5" HAlign="haRight" ParentFont="false" Text="[MaxVol0]"/>
      <TfrxMemoView Name="Memo31" AllowVectorExport="true" Left="257.008044013081" Top="0" Width="45.3543612382555" Height="17.0078843379581" Font.Charset="1" Font.Color="0" Font.Height="-11" Font.Name="Arial" Font.Style="0" Frame.Typ="15" Frame.Width="0.5" HAlign="haRight" ParentFont="false" Text="[Density0]"/>
      <TfrxMemoView Name="Memo32" AllowVectorExport="true" Left="302.362396240234" Top="0" Width="45.3543612382555" Height="17.0078843379581" Font.Charset="1" Font.Color="0" Font.Height="-11" Font.Name="Arial" Font.Style="0" Frame.Typ="15" Frame.Width="0.5" HAlign="haRight" ParentFont="false" Text="[Fill0]"/>
      <TfrxMemoView Name="Memo33" AllowVectorExport="true" Left="347.716748467388" Top="0" Width="52.9134184409309" Height="17.0078843379581" Font.Charset="1" Font.Color="0" Font.Height="-11" Font.Name="Arial" Font.Style="0" Frame.Typ="15" Frame.Width="0.5" HAlign="haRight" ParentFont="false" Text="[Mass0]"/>
      <TfrxMemoView Name="Memo34" AllowVectorExport="true" Left="400.630153391667" Top="0" Width="45.3543612382555" Height="17.0078843379581" Font.Charset="1" Font.Color="0" Font.Height="-11" Font.Name="Arial" Font.Style="0" Frame.Typ="15" Frame.Width="0.5" HAlign="haRight" ParentFont="false" Text="[VCG0]"/>
      <TfrxMemoView Name="Memo35" AllowVectorExport="true" Left="445.984505618821" Top="0" Width="52.9134184409309" Height="17.0078843379581" Font.Charset="1" Font.Color="0" Font.Height="-11" Font.Name="Arial" Font.Style="0" Frame.Typ="15" Frame.Width="0.5" HAlign="haRight" ParentFont="false" Text="[TCG0]"/>
      <TfrxMemoView Name="Memo36" AllowVectorExport="true" Left="498.897910543099" Top="0" Width="52.9134184409309" Height="17.0078843379581" Font.Charset="1" Font.Color="0" Font.Height="-11" Font.Name="Arial" Font.Style="0" Frame.Typ="15" Frame.Width="0.5" HAlign="haRight" ParentFont="false" Text="[LCG0]"/>
      <TfrxMemoView Name="Memo37" AllowVectorExport="true" Left="551.811315467377" Top="0" Width="52.9134184409309" Height="17.0078843379581" Font.Charset="1" Font.Color="0" Font.Height="-11" Font.Name="Arial" Font.Style="0" Frame.Typ="15" Frame.Width="0.5" HAlign="haRight" ParentFont="false" Text="[FSM0]"/>
      <TfrxMemoView Name="Memo38" AllowVectorExport="true" Left="604.724720391656" Top="0" Width="52.9134184409309" Height="17.0078843379581" Font.Charset="1" Font.Color="0" Font.Height="-11" Font.Name="Arial" Font.Style="0" Frame.Typ="15" Frame.Width="0.5" HAlign="haRight" ParentFont="false" Text="[MAXFSM0]"/>
      <TfrxMemoView Name="Memo39" AllowVectorExport="true" Left="657.638125315934" Top="0" Width="39.6850627043104" Height="17.0078843379581" Font.Charset="1" Font.Color="0" Font.Height="-11" Font.Name="Arial" Font.Style="0" Frame.Typ="15" Frame.Width="0.5" HAlign="haRight" ParentFont="false" Text="[Sounding0]"/>
      <TfrxMemoView Name="Memo40" AllowVectorExport="true" Left="697.32316098694" Top="0" Width="39.6850627043104" Height="17.0078843379581" Font.Charset="1" Font.Color="0" Font.Height="-11" Font.Name="Arial" Font.Style="0" Frame.Typ="15" Frame.Width="0.5" HAlign="haRight" ParentFont="false" Text="[MaxSnd0]"/>
    </TfrxSubdetailData>
So out of desperation (and this is a really cumbersome method), I am now trying to modify the text (string) for the line I want to change the colour, so that I can search all the Memo's of the entire Report for that modified text and then hopefully change the color and then re-modify the text to its original.

Which I am doing via the OnBeforePrint Event.

So as an example I have added the characters >> to the beginning of the Tank Name for the line I want to change color, as per the attached screen shot.

My plan is to search all Memo's for Strings that start with those characters, set the flag to change the color and then delete those characters from the string and re-insert the string back into the report.

But my problem is that when extracting the text from this cell (or Memo) it is in the form of a VARIANT, and I do not know how to either compare the first two characters of a VARIANT so as to trigger my color change, OR to convert the VARIANT to a STRING so that I can then do the string comare with a string.

Code: Select all

void __fastcall TMainFRReport::frxReport2BeforePrint(TfrxReportComponent *Sender)
{

  TfrxMemoView * CallMemo1 = dynamic_cast <TfrxMemoView *> (Sender);

	if (strncpy(CallMemo1->Value,">>",2) == 1)        //Error Cant convert Variant to char * // I can't find a way to compare 1st two characters of VARIANT (Value) with a string ">>" to act as the trigger to change colour
	  CallMemo1->Font->Color = clRed;
	else
	  CallMemo1->Font->Color = clBlack;

}
//---------------------------------------------------------------------------
Apologies for the long (and possibly cumbersome) question. (Almost as cumbersome as my work around)
Attachments
Capture05.PNG
Capture05.PNG (130.44 KiB) Viewed 424 times
theLizard
BCBJ Master
BCBJ Master
Posts: 457
Joined: Wed Mar 18, 2009 2:14 pm

Re: Converting VARIANTs and FASTREPORT 6

Post by theLizard »

kingbarsa wrote: Wed Oct 28, 2020 1:02 am However where the Memo's or my my case cells, are defined via an Array Dataset,
Can you give us an example of what is in the array data set?

It may be possible to have all the information needed to set color in advance so that you need not check for ">>" in a variant.

I don't have enough info to understand the issue you are having but, I have done string grid cell color changes based on dynamic cell conditions in large data samples.

Where does the data come from to fill the TfrxMemoView for the Memo's (these are unique in appearance), can the determination of color be set prior to setting the TfrxMemoView?

I have an idea for the frxReport2BeforePrint method but I need to understand better what your data is, how you assign it to a view etc, is the color change determined by a value etc.

Cheers
kingbarsa
Posts: 5
Joined: Tue Oct 20, 2020 7:06 am

Re: Converting VARIANTs and FASTREPORT 6

Post by kingbarsa »

To first answer your question on where the data comes from.

The data is originally in Struct Arrays of type AnsiString for the Tank Names and floats for the remaining parameters.

Whilst building the FastReport, I first convert them all the Struct Arrays to type AnsiString, as follows:

Code: Select all

 for (int j=0; j<LiquidLoads->TankBasicData->NumberOfTanks[i]; ++j)
	  {

		  PrevBottom += CellHeight;

		  TankList[i][j]->TankName = LiquidLoads->TankHeaderArray[i][j]->TankName;
		  if (LiquidLoads->TankHeaderArray[i][j]->SelectForUse == true)
			 TankList[i][j]->TankName = ">> " + TankList[i][j]->TankName;
		  
		  TankList[i][j]->Fill = FloatToStrF(LiquidLoads->TankCalcArray[i][j]->CalcFill*100, ffNumber, 10, 1) + "%";
		  TankList[i][j]->MaxVol = FloatToStrF(LiquidLoads->TankHeaderArray[i][j]->MaxVol, ffNumber, 10, 2);
		  TankList[i][j]->Density = FloatToStrF(LiquidLoads->TankCalcArray[i][j]->CalcDensity, ffNumber, 10, 3);
		  TankList[i][j]->Mass = FloatToStrF(LiquidLoads->TankCalcArray[i][j]->CalcMass, ffNumber, 10, 2);
		  TankList[i][j]->VCG = FloatToStrF(LiquidLoads->TankCalcArray[i][j]->CalcVcg, ffNumber, 10, 3);
		  TankList[i][j]->TCG = FloatToStrF(LiquidLoads->TankCalcArray[i][j]->CalcTcg, ffNumber, 10, 3);
		  TankList[i][j]->LCG = FloatToStrF(LiquidLoads->TankCalcArray[i][j]->CalcLcg, ffNumber, 10, 3);
		  TankList[i][j]->FSM = FloatToStrF(LiquidLoads->TankCalcArray[i][j]->CalcFsm, ffNumber, 10, 2);
		  TankList[i][j]->MAXFSM = FloatToStrF(LiquidLoads->TankCalcArray[i][j]->CalcMaxFsm, ffNumber, 10, 2);
		  TankList[i][j]->Sounding = FloatToStrF(LiquidLoads->TankCalcArray[i][j]->CalcSounding, ffNumber, 10, 2);
		  TankList[i][j]->MaxSnd = FloatToStrF(LiquidLoads->TankHeaderArray[i][j]->MaxSnd, ffNumber, 10, 2);

	   }
You will also see where I add the >> to the Tank Name. BTW there are about four scenarios where I would want to change colours, this is just to get the one working, so I can then take it further from there.

Also the color change is not a function of value. It is a user selection, in this instance to indicate which of the tanks are considered to be taking suction (being in use) but as mentioned there are 3 other scenarios (all user selections) which would ultimately influence colours.

Next I will indicate a snippet of how the memo's are built at run time

Code: Select all

        for (int i=0; i<NoLiquidTypes; ++i)
	{
	.
	// Create the Group Header
	  GroupHeader = new TfrxGroupHeader(Page);
	  GroupHeader->CreateUniqueName();.
	.
	.
	.
         // add an Memo object to the report Detail band
	  Memo = new TfrxMemoView(GroupHeader);
	  Memo->CreateUniqueName();
	  .
	  .
	  .  
          //dsArray0 are dynamically sized according to the required range (number of tanks in that liquid group)
          if (i==0)
	  {
	   dsArray0->RangeEndCount = LiquidLoads->TankBasicData->NumberOfTanks[i];
	   SubDetailBand->DataSet = dsArray0;
	  }
	  if (i==1)
	  {
	   dsArray1->RangeEndCount = LiquidLoads->TankBasicData->NumberOfTanks[i];
	   SubDetailBand->DataSet = dsArray1;
	  }
	  ........//another 8 dsArrays  follow (maximum of 10 Liquid Types allowed)
  .
  .
  .
  .
  // Start creating the memo cells. Note the Variable Naming convention "[TankName" + IntToStr(i) + "]";  etc
  // So in the case of i=0, there will be  LiquidLoads->TankBasicData->NumberOfTanks[0] number of lines in this array, as example
  // add a TankName object Memo to the report Detail band
	  Memo = new TfrxMemoView(SubDetailBand);
	  Memo->CreateUniqueName();
	  Memo->Top = 0. * fr1cm;
	  Memo->Left = 0.4 * fr1cm;
	  Memo->Height = CellHeight * fr1cm;
	  Memo->Width = CellWidth0 * fr1cm;
	  Memo->HAlign = haLeft;
	  Memo->Font->Size = fontsize;
	  VariableName = "[TankName" + IntToStr(i) + "]";
	  Memo->Text = VariableName;
	  Memo->Frame->Typ = TfrxFrameTypes();
	  Memo->Frame->Typ = Memo->Frame->Typ << ftTop << ftBottom << ftLeft << ftRight;
	  Memo->Frame->Width = 0.5;
	  PrevRight = (Memo->Width + Memo->Left)/fr1cm ;

// add an MaxVol object to the report Detail band
	  Memo = new TfrxMemoView(SubDetailBand);
	  Memo->CreateUniqueName();
	  Memo->Top = 0. * fr1cm;
	  Memo->Left = PrevRight * fr1cm;
	  Memo->Height = CellHeight * fr1cm;
	  Memo->Width = CellWidth1 * fr1cm;
	  Memo->HAlign = haRight;
	  Memo->Font->Size = fontsize;
	  VariableName = "[MaxVol" + IntToStr(i) + "]";
	  Memo->Text = VariableName;
	  PrevRight += (Memo->Width)/fr1cm ;
	  Memo->Frame->Typ = TfrxFrameTypes();
	  Memo->Frame->Typ = Memo->Frame->Typ << ftTop << ftBottom << ftLeft << ftRight;
	  Memo->Frame->Width = 0.5;
	  ...
	  // Adds another 10 columns by the same method.  (See previous screenshot for columns)
Lastly to show a snippet of how the Struct Array strings are transferred to the FastReport memo's in the GetValue event.

Code: Select all

void __fastcall TMainFRReport::frxReport2GetValue(const UnicodeString VarName, Variant &Value)

{
   UnicodeString VariableName;


  for (int i=0; i<NoLiquidTypes; ++i)
  {

	if (i==0)
	{
	VariableName = "TankName" + IntToStr(i);
	if(CompareText(VarName,VariableName) == 0)
	 Value = TankList[i][dsArray0->RecNo]->TankName;

	if(CompareText(VarName,"MaxVol" + IntToStr(i)) == 0)
	 Value = TankList[i][dsArray0->RecNo]->MaxVol;

	if(CompareText(VarName,"Density" + IntToStr(i)) == 0)
	 Value = TankList[i][dsArray0->RecNo]->Density;

	if(CompareText(VarName,"Fill" + IntToStr(i)) == 0)
	 Value = TankList[i][dsArray0->RecNo]->Fill;

	if(CompareText(VarName,"Mass" + IntToStr(i)) == 0)
	 Value = TankList[i][dsArray0->RecNo]->Mass;

	if(CompareText(VarName,"VCG" + IntToStr(i)) == 0)
	 Value = TankList[i][dsArray0->RecNo]->VCG;

	if(CompareText(VarName,"TCG" + IntToStr(i)) == 0)
	 Value = TankList[i][dsArray0->RecNo]->TCG;

	if(CompareText(VarName,"LCG" + IntToStr(i)) == 0)
	 Value = TankList[i][dsArray0->RecNo]->LCG;

	if(CompareText(VarName,"FSM" + IntToStr(i)) == 0)
	 Value = TankList[i][dsArray0->RecNo]->FSM;

	if(CompareText(VarName,"MAXFSM" + IntToStr(i)) == 0)
	 Value = TankList[i][dsArray0->RecNo]->MAXFSM;

	if(CompareText(VarName,"Sounding" + IntToStr(i)) == 0)
	 Value = TankList[i][dsArray0->RecNo]->Sounding;

	if(CompareText(VarName,"MaxSnd" + IntToStr(i)) == 0)
	 Value = TankList[i][dsArray0->RecNo]->MaxSnd;
	}
	.
	.
	.
	//repeated for i=1, i=2......i=10  
	
	
So the entire Struct Array string is transferred to Value in one step. Thus a Memo->Value in these instances is not one value, but the whole array of values (and transferred in one step).

The repetition of code for i=1, i=2, .... i=10 is not the most efficient, as it is repeated code, but found necessary due to the dsArray0, dsArray1 ... dsArray10, being unique components dropped on the form, with unique names, hence could not loop them.

Apologies for the long snippets of code. Always hard to judge how much to cut out, before it detracts from conveying the required information for someone else to understand.

Thanks. Appreciated.
Post Reply