cancel
Showing results for 
Search instead for 
Did you mean: 

CR .Net - Getting field values for each section at runtime

Former Member
0 Kudos

I am porting our integration with CR from the old COM based component to CR .Net.  I'm using the latest version ((v.13.0.13.1597) for Visual Studio.

Our reports contain BLOB fields which are used throughout the sections, including repeating Details sections.  Our database stores the desired width, height, and position of the BLOB field. For convenience, we add the width/height/position database fields as suppressed fields in the report so that we can easily access the values at runtime.

In our existing COM implementation we hook into the ISectionFormat event for each section that contains a BLOB field, and then when these events fire we iterate through the ReportObjects in the section to locate our dimension/position fields by name, something like...

IReportObjectPtr l_ReportObjectPtr = pReport->GetSections()->Item[ sectionNumber ]->GetReportObjects()->Item[ reportObjectIndex ];

        if(l_ReportObjectPtr->Kind == crFieldObject )

        {

            l_FieldObject = l_ReportObjectPtr;

            if( l_FieldObject->Name.GetBSTR() == HEIGHT_FIELD_NAME)

                m_lfImageHeight = l_FieldObject->Value;

          }

Once we have the values, we then again iterate through the ReportObjects in the Section that triggered the event to find the BLOB field and set the width/height/top/left values on the fieldObject accordingly.

How do I achieve this with the .NET SDK as the FieldObject->Value is no longer available?

I know that I can use the RAS SDK to access the data at runtime, but I can't seem to find any concept of the "current" row.  I can hook into the new FormatSection event but there doesn't appear to be a way to find the section object that fired the event to get to the fields within it, or to then access the corresponding data values.

The overarching requirement is to allow our users to store BLOB images in our database along with the dimensions (in TWIPS).  When they print the report, the BLOB's (and the sections within them) need to be resized on a row by row (section by section) basis to match the dimensions stored in the database.   Is there a different way to achieve this in with the .NET SDK's if I can no longer do it the way we did with the COM component?

Accepted Solutions (1)

Accepted Solutions (1)

0 Kudos

Hi Paul,

Yes there are a lot of event triggers lost when we updated to .NET. Some are simply due to .NET not being capable of capturing the event...

See if this gets you going:

CrystalDecisions.ReportAppServer.ClientDoc.ISCDReportClientDocument rptClientDoc;

rptClientDoc = rpt.ReportClientDocument;

//DateTime dtStart;

//dtStart = DateTime.Now;

//btnSQLStatement.Text += "\nReport End time: \n" + dtStart.ToString();

rptClientDoc.ReportOptions.ConvertNullFieldToDefault = true;

rptClientDoc.ReportOptions.ConvertOtherNullsToDefault = true;

btnReportObjects.Text = "";

int t = 0;

if (e.ObjectInfos != null)

{

    foreach (ObjectInfo oi in e.ObjectInfos)

    {

        try

        {

            if (oi.ObjectType.ToString() != "GroupChart")

            {

                if (oi.ObjectType.ToString() != "OleObject")

                {

                    if (oi.ObjectType.ToString() != "CrossTab")

                    {

                        // This is the field you double clicked on, in the viewer

                        if (oi.Name == e.ObjectInfo.Name)

                            btnReportObjects.Text += ">>> SELECTED OBJECT - you clicked on<<<" + "\n";

                        btnReportObjects.Text += "DataContext: " + oi.DataContext.ToString() + "\n";

                        btnReportObjects.Text += "GroupNamePath: " + oi.GroupNamePath.ToString() + "\n";

                        btnReportObjects.Text += "Hyperlink: " + oi.Hyperlink.ToString() + "\n";

                        string textBox1 = String.Empty;

                        foreach (FormulaField resultField in rptClientDoc.DataDefController.DataDefinition.FormulaFields)

                        {

                            CrystalDecisions.ReportAppServer.ReportDefModel.ReportObjects FormulaFldobjs;

                            FormulaFldobjs = rptClientDoc.ReportDefController.ReportObjectController.GetReportObjectsByKind(CrReportObjectKindEnum.crReportObjectKindField);

                            t = rptClientDoc.DataDefController.DataDefinition.FormulaFields.FindIndexOf(resultField);

                            CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject objField;

                            objField = (CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject)FormulaFldobjs[t];

                            CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject objField2 = (CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject)objField.Clone(true);

                            if (oi.Name.ToString() == objField2.Name.ToString())

                            {

                                btnReportObjects.Text += "Name: " + oi.Name.ToString() + " -> " + objField2.DataSourceName.ToString() + "\n";

                            }

                            t++;

                        }

                        //btnReportObjects.Text += "Name: " + oi.Name.ToString() + "\n";

                        btnReportObjects.Text += "Text: " + oi.Text.ToString() + "\n";

                        btnReportObjects.Text += "ObjectType: " + oi.ObjectType.ToString() + "\n";

                        btnReportObjects.Text += "Tooltip: " + oi.ToolTip.ToString() + "\n";

                        btnReportObjects.Text += "========================\n";

                        btnReportObjects.Text += richTextBox1;

                        btnReportObjects.AppendText(" 'End' \n");

                    }

                }

            }

        }

        catch (Exception ex)

        {

            MessageBox.Show("ERROR: " + ex.Message);

        }

    }

}

Add it to the DoubleClick event, so when you click on a report object in the viewer it should return info about the object.

Don

Former Member
0 Kudos

Hi Don,

That appears to help if the event is occurs for a particular object in the report, but how can I extend this approach to access fields within a section before it is rendered?  Essentially I need to:

- intercept the rendering of each section

- check to see whether there are any BLOB fields in the section

- if so look through the other fields in the section to find specific fields by name (that contain the height/width/offset values)

- grab the underlying value for those height/width/offset fields based on the "current" row in the dataset being processed

- update the BLOB object dimensions / offset with these values

At the moment I don't see a way to access the FieldObjects within a section that fired a SectionFormat event.  If I could do that, then I believe your approach above would allow me to access the underlying FieldObject, but I still dont see how to access the runtime value of the FieldObject. What am I missing here?

Thanks

Paul

0 Kudos

HI Paul,

This way.... This only reads all of the info so run indebug mode and you'll find all of the properties...

case "Object Name -> Field Name":
    #region OBJtoFName
    btnReportObjects.Text = "";
    textBox1 = "";
    flcnt = 0;

    CrystalDecisions.ReportAppServer.ReportDefModel.ReportObjects rptObjs;
    //rptObjs = rptClientDoc.ReportDefController.ReportObjectController.GetReportObjectsByKind(CrReportObjectKindEnum.crReportObjectKindField);
    rptObjs = rptClientDoc.ReportDefController.ReportObjectController.GetAllReportObjects();

    foreach (CrystalDecisions.ReportAppServer.ReportDefModel.ReportObject rptObj1 in rptObjs)
    {
        switch (rptObj1.Kind)
        {
            case CrReportObjectKindEnum.crReportObjectKindField:
                CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject fldObj1;
                fldObj1 = (CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject)rptObj1;
                               
                textBox1 = fldObj1.Name.ToString();
                textBox1 += " -> ";
                textBox1 += fldObj1.DataSourceName.ToString() + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                break;
            case CrReportObjectKindEnum.crReportObjectKindText:
                CrystalDecisions.ReportAppServer.ReportDefModel.TextObject txtObj;
                txtObj = (CrystalDecisions.ReportAppServer.ReportDefModel.TextObject)rptObj1;
                textBox1 = txtObj.Name.ToString();
                textBox1 += " -> " + txtObj.Text.ToString();
                textBox1 += "\nEnableSuppressEmbedBlankLines: " + ((dynamic) rptObj1).TextObjectFormat.EnableSuppressEmbedBlankLines + "\n";
                textBox1 += "SectionCode: " + ((dynamic) rptObj1).SectionCode;
                btnReportObjects.Text += textBox1 + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                break;

            case CrReportObjectKindEnum.crReportObjectKindBox:
                CrystalDecisions.ReportAppServer.ReportDefModel.BoxObject boxObj1;
                CrystalDecisions.ReportAppServer.ReportDefModel.BoxObject boxObj2 = new CrystalDecisions.ReportAppServer.ReportDefModel.BoxObject();
                boxObj1 = (CrystalDecisions.ReportAppServer.ReportDefModel.BoxObject)rptObj1;
                boxObj2 = boxObj1;

                textBox1 = boxObj1.Name.ToString();
                textBox1 += " -> ";
                textBox1 += boxObj1.Name.ToString();
                textBox1 += " : X - ";
                textBox1 += (boxObj1.Left / 1440.00).ToString();
                textBox1 += " : Y - ";
                textBox1 += ((boxObj1.Right - boxObj1.Left) / 1440.00).ToString();
                textBox1 += " : Width - ";
                textBox1 += (boxObj1.Width / 1440.00).ToString();
                textBox1 += " : Height - ";
                textBox1 += (boxObj1.Height / 1440.00).ToString();
                btnReportObjects.Text += textBox1 + "\n";
                btnReportObjects.Text += "Section Name: " + rptObj1.SectionName.ToString() + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                IsRpt = false;

                break;

            case CrReportObjectKindEnum.crReportObjectKindPicture:
                textBox1 = rptObj1.Name.ToString();
                textBox1 += " -> ";
                textBox1 += rptObj1.Name.ToString();
                btnReportObjects.Text += textBox1;
                btnReportObjects.AppendText("\n");
                btnReportObjects.Text += "Height: " + rptObj1.Height.ToString();
                btnReportObjects.AppendText(" Twips\n");
                btnReportObjects.Text += "Width: " + rptObj1.Width.ToString();
                btnReportObjects.AppendText(" Twips\n");
                btnReportObjects.Text += "Top: " + rptObj1.Top.ToString();
                btnReportObjects.AppendText(" Twips\n");
                btnReportObjects.Text += "Left: " + rptObj1.Left.ToString();
                btnReportObjects.AppendText(" Twips\n");
                btnReportObjects.Text += "Section Name: " + rptObj1.SectionName.ToString() + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                break;

            case CrReportObjectKindEnum.crReportObjectKindChart:
                textBox1 = rptObj1.Name.ToString();
                textBox1 += " -> ";
                textBox1 += rptObj1.Name.ToString();
                btnReportObjects.Text += textBox1;
                btnReportObjects.AppendText("\n");
                btnReportObjects.Text += "Height: " + rptObj1.Height.ToString();
                btnReportObjects.AppendText(" Twips\n");
                btnReportObjects.Text += "Width: " + rptObj1.Width.ToString();
                btnReportObjects.AppendText(" Twips\n");
                btnReportObjects.Text += "Top: " + rptObj1.Top.ToString();
                btnReportObjects.AppendText(" Twips\n");
                btnReportObjects.Text += "Left: " + rptObj1.Left.ToString();
                btnReportObjects.AppendText(" Twips\n");
                btnReportObjects.Text += "Section Name: " + rptObj1.SectionName.ToString() + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                break;

            case CrReportObjectKindEnum.crReportObjectKindSubreport:
                CrystalDecisions.ReportAppServer.ReportDefModel.SubreportObject subObj1;
                subObj1 = (CrystalDecisions.ReportAppServer.ReportDefModel.SubreportObject)rptObj1;

                textBox1 = subObj1.Name.ToString();
                textBox1 += " -> ";
                textBox1 += subObj1.SubreportName.ToString() + " - ";
                btnReportObjects.Text += textBox1;
                btnReportObjects.Text += "Section Name: " + rptObj1.SectionCode.ToString() + " " + rptObj1.SectionName.ToString() + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                break;

            case CrReportObjectKindEnum.crReportObjectKindOlapGrid:
                CrystalDecisions.ReportAppServer.ReportDefModel.OlapGridObject OLAPObj1;
                OLAPObj1 = (CrystalDecisions.ReportAppServer.ReportDefModel.OlapGridObject)rptObj1;

                textBox1 = OLAPObj1.Name.ToString();
                textBox1 += " -> ";
                textBox1 += OLAPObj1.Name.ToString() + " - ";
                btnReportObjects.Text += textBox1;
                btnReportObjects.Text += "Section Name: " + rptObj1.SectionCode.ToString() + " " + rptObj1.SectionName.ToString() + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                break;

            case CrReportObjectKindEnum.crReportObjectKindMap:
                CrystalDecisions.ReportAppServer.ReportDefModel.MapObject MapObj1;
                MapObj1 = (CrystalDecisions.ReportAppServer.ReportDefModel.MapObject)rptObj1;

                textBox1 = MapObj1.Name.ToString();
                textBox1 += " -> ";
                textBox1 += MapObj1.Name.ToString() + " - ";
                btnReportObjects.Text += textBox1;
                btnReportObjects.Text += "Section Name: " + rptObj1.SectionCode.ToString() + " " + rptObj1.SectionName.ToString() + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                break;

            case CrReportObjectKindEnum.crReportObjectKindLine:
                CrystalDecisions.ReportAppServer.ReportDefModel.LineObject LineObj1;
                LineObj1 = (CrystalDecisions.ReportAppServer.ReportDefModel.LineObject)rptObj1;

                textBox1 = LineObj1.Name.ToString();
                textBox1 += " -> ";
                textBox1 += LineObj1.Name.ToString() + " - ";
                btnReportObjects.Text += textBox1;
                btnReportObjects.Text += "Section Name: " + rptObj1.SectionCode.ToString() + " " + rptObj1.SectionName.ToString() + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                break;

            case CrReportObjectKindEnum.crReportObjectKindFlash:
                CrystalDecisions.ReportAppServer.ReportDefModel.FlashObject FlashObj1;
                FlashObj1 = (CrystalDecisions.ReportAppServer.ReportDefModel.FlashObject)rptObj1;

                textBox1 = FlashObj1.Name.ToString();
                textBox1 += " -> ";
                textBox1 += FlashObj1.Name.ToString() + " - ";
                btnReportObjects.Text += textBox1;
                btnReportObjects.Text += "Section Name: " + rptObj1.SectionCode.ToString() + " " + rptObj1.SectionName.ToString() + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                break;

            case CrReportObjectKindEnum.crReportObjectKindFieldHeading:
                CrystalDecisions.ReportAppServer.ReportDefModel.FieldHeadingObject FieldHeadingObj1;
                FieldHeadingObj1 = (CrystalDecisions.ReportAppServer.ReportDefModel.FieldHeadingObject)rptObj1;

                textBox1 = FieldHeadingObj1.Name.ToString();
                textBox1 += " -> ";
                textBox1 += FieldHeadingObj1.Name.ToString() + " - ";
                btnReportObjects.Text += textBox1;
                btnReportObjects.Text += "Section Name: " + rptObj1.SectionCode.ToString() + " " + rptObj1.SectionName.ToString() + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                break;

            case CrReportObjectKindEnum.crReportObjectKindCrosstab:
                CrystalDecisions.ReportAppServer.ReportDefModel.CrossTabObject CrossObj1;
                CrossObj1 = (CrystalDecisions.ReportAppServer.ReportDefModel.CrossTabObject)rptObj1;

                textBox1 = CrossObj1.Name.ToString();
                textBox1 += " -> ";
                textBox1 += CrossObj1.Name.ToString() + " - ";
                btnReportObjects.Text += textBox1;
                btnReportObjects.Text += "Section Name: " + rptObj1.SectionCode.ToString() + " " + rptObj1.SectionName.ToString() + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                break;

            case CrReportObjectKindEnum.crReportObjectKindBlobField:
                CrystalDecisions.ReportAppServer.ReportDefModel.BlobFieldObject BlobObj1;
                BlobObj1 = (CrystalDecisions.ReportAppServer.ReportDefModel.BlobFieldObject)rptObj1;

                textBox1 = BlobObj1.Name.ToString();
                textBox1 += " -> ";
                textBox1 += BlobObj1.Name.ToString() + " - ";
                btnReportObjects.Text += textBox1;
                btnReportObjects.Text += "Section Name: " + rptObj1.SectionCode.ToString() + " " + rptObj1.SectionName.ToString() + "\n";
                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");
                ++flcnt;
                btnCount.Text = flcnt.ToString();
                break;

            //case CrReportObjectKindEnum.crReportObjectKindInvalid:
            //    CrystalDecisions.ReportAppServer.ReportDefModel. InvalidObj1;
            //    BlobObj1 = (CrystalDecisions.ReportAppServer.ReportDefModel.BlobFieldObject)rptObj1;

            //    textBox1 = BlobObj1.Name.ToString();
            //    textBox1 += " -> ";
            //    textBox1 += BlobObj1.Name.ToString() + " - ";
            //    btnReportObjects.Text += textBox1;
            //    btnReportObjects.Text += "Section Name: " + rptObj1.SectionCode.ToString() + " " + rptObj1.SectionName.ToString() + "\n";
            //    btnReportObjects.AppendText("\n");
            //    ++flcnt;
            //    btnCount.Text = flcnt.ToString();
            //    break;
            //    //CrystalDecisions.ReportAppServer.ReportDefModel.CrReportObjectKindEnum.crReportObjectKindInvalid;


        }
    }
    #endregion OBJtoFName
    break;

Don

Former Member
0 Kudos

Hi Don,

Thanks for your continued help, but it is still not making sense to me.  How do I get from the FormatSection event handler to here?  I see the FormatSectionEventArgs contains a SectionCode, so if I iterate through the report objects in rptClientDoc.ReportDefController.ReportObjectController.GetAllReportObjects() and search for one with a matching SectionCode, that should indicate that the report object exists in the section being formatted.  Is that correct? 

But I'm still not seeing what line of code in either of your examples actually gets the field value at runtime.

Thanks in advance

0 Kudos

Hi Paul,

You have to create an event on the Double click, lightning bolt on the properties of the Viewer,

The set the event to call this:

private void crystalReportViewer1_DoubleClickPage(object sender, PageMouseEventArgs e)
{
    rptClientDoc.ReportOptions.ConvertNullFieldToDefault = true;
    rptClientDoc.ReportOptions.ConvertOtherNullsToDefault = true;

    btnReportObjects.Text = "";
    int t = 0;
    if (e.ObjectInfos != null)
    {
        foreach (ObjectInfo oi in e.ObjectInfos)
        {
            try
            {
                if (oi.ObjectType.ToString() != "GroupChart")
                {
                    if (oi.ObjectType.ToString() != "OleObject")
                    {
                        if (oi.ObjectType.ToString() != "CrossTab")
                        {
                            // This is the field you double clicked on, in the viewer
                            if (oi.Name == e.ObjectInfo.Name)
                                btnReportObjects.Text += @">>> SELECTED OBJECT - you clicked on<<<\n";

                            btnReportObjects.Text += "DataContext: " + oi.DataContext.ToString() + "\n";
                            btnReportObjects.Text += "GroupNamePath: " + oi.GroupNamePath.ToString() + "\n";
                            btnReportObjects.Text += "Hyperlink: " + oi.Hyperlink.ToString() + "\n";

                            string textBox1 = String.Empty;
                            foreach (FormulaField resultField in rptClientDoc.DataDefController.DataDefinition.FormulaFields)
                            {
                                CrystalDecisions.ReportAppServer.ReportDefModel.ReportObjects FormulaFldobjs;
                                FormulaFldobjs = rptClientDoc.ReportDefController.ReportObjectController.GetReportObjectsByKind(CrReportObjectKindEnum.crReportObjectKindField);
                                t = rptClientDoc.DataDefController.DataDefinition.FormulaFields.FindIndexOf(resultField);
                                CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject objField;
                                objField = (CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject)FormulaFldobjs[t];
                                CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject objField2 = (CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject)objField.Clone(true);

                                if (oi.Name.ToString() == objField2.Name.ToString())
                                {
                                    btnReportObjects.Text += "Name: " + oi.Name.ToString() + " -> " + objField2.DataSourceName.ToString() + "\n";
                                }

                                t++;
                            }

                            //btnReportObjects.Text += "Name: " + oi.Name.ToString() + "\n";
                            btnReportObjects.Text += "Value: " + oi.Text.ToString() + "\n";
                            btnReportObjects.Text += "ObjectType: " + oi.ObjectType.ToString() + "\n";
                            btnReportObjects.Text += "Tooltip: " + oi.ToolTip.ToString() + "\n";
                            btnReportObjects.Text += "========================\n";
                            //btnReportObjects.Text += richTextBox1;
                            btnReportObjects.AppendText("\n\n");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("ERROR: " + ex.Message);
            }
        }
    }
}

It will display all of the info on that row of objects.

Don

Former Member
0 Kudos

Hi Don,

I'm finally getting around to working through your examples and understanding them, but don't believe it answers my question.  The ObjectInfos that contain data for the current row only apply to user-driven events such as where the user double clicks a value.  The ObjectInfos are not available for formatting events such as the FormatSection event, so I still don't understand how to access the data for the row currently being rendered when a FormatSection event fires.  You've alluded that certain events changed in the move to Crystal.Net, so are you saying that this is no longer possible?

To reiterate my scenario, for every section in a report, I want to check to see whether that section contains any BLOB fields and, if so, set the dimensions and position of that BLOB based on other (suppressed) field values that exist in the same section.

Thanks

Paul

0 Kudos

Hi Paul,

I pasted in the code already to get the object info, you just had to look for it:

            case CrReportObjectKindEnum.crReportObjectKindBlobField:
                CrystalDecisions.ReportAppServer.ReportDefModel.BlobFieldObject BlobObj1;
                BlobObj1 = (CrystalDecisions.ReportAppServer.ReportDefModel.BlobFieldObject)rptObj1;

                textBox1 = BlobObj1.Name.ToString();

                textBox1 += " -> ";

                textBox1 += BlobObj1.Name.ToString() + " - ";

                btnReportObjects.Text += textBox1;

                btnReportObjects.Text += "Section Name: " + rptObj1.SectionCode.ToString() + " " + rptObj1.SectionName.ToString() + "\n";

                btnReportObjects.AppendText("ToolTip: " + rptObj1.Format.ToolTipText.ToString() + "\n\n");

                ++flcnt;

                btnCount.Text = flcnt.ToString();

                break

And to get the location info use this:

btnReportObjects.Text += "Height: " + BlobObj1.Height.ToString();

btnReportObjects.AppendText(" Twips\n");

btnReportObjects.Text += "Width: " + BlobObj1.Width.ToString();

btnReportObjects.AppendText(" Twips\n");

btnReportObjects.Text += "Top: " + BlobObj1.Top.ToString();

btnReportObjects.AppendText(" Twips\n");

btnReportObjects.Text += "Left: " + BlobObj1.Left.ToString();

btnReportObjects.AppendText(" Twips\n");

Don

Former Member
0 Kudos

Hi Don,

I understand how to use the API to read/set the values on report objects such as the BLOB object, that's no problem.  I also understand how to search the report objects to find a BLOB field.  But this is only in the report design, prior to it being loaded with data / displayed.  What I don't understand is

1) How to find the section object that is currently being rendered, from within a FormatSection event handler.  Or from there how to find the BLOB that is currently being rendered.  If I design a report that has one details section containing one BLOB, and then set a datasource with 100 rows, I would expect the FormatSection event to be called 100 times and therefore have 100 different BLOB instances to manipulate.  The code in your first example iterates through the rptClientDoc.ReportDefController.ReportObjectController.GetAllReportObjects() which appear to be design-time, i.e. in there is only 1 BLOB object.  How do I access / manipulate the runtime instances of the BLOB objects?

2) How to find the runtime value - as populated from the database - for a given field (I know the field name).  Similar to the above, I need to be able to access the field from the same section that is currently being rendered.  So if I design the report with one field next to my BLOB, I would expect there to be 100 instances at runtime, one for each row in the database.

My understanding is that I can use the RowSetController to browse the field values, which I'm going to pre-empt is the solution to question 2, but that is no use from within a FormatSection event unless there is a concept of the "current" row.    It is also no use if I can't iterate through / access the BLOB object instances that are being rendered. 

Thanks

Paul

EDIT: I think I have made progress on point 1, and believe that if I modify BLOB dimensions/position via the ReportDocument->ReportClientDocument->ReportDefController->ReportObjectController->GetAllReportObjects() from within the FormatSection event handler, this will change the instance of the BLOB being rendered in that section.  I have managed to map the section index to the section code of each BLOB prior to rendering, allowing me to work out which actual section object the BLOB exists in from that (seemingly random) section code that is in the FormatSection event args.  So provided this assumption is correct, and there is an answer to 2, I think it should work.

0 Kudos

Good day Paul,

Kevin, Fritz and Chuck R. contacted me about this also but best to update here.

I went through my code again and not sure why but here is a better example using the Double Click event to get the value from the viewer.

The problem is until the report is rendered there is no way to get what value is going to be in the object that I can think of right now....

With your update to the BLOB field (#2) it appears you are using the viewers event trigger so this may help. But this is after the page is rendered.

I don't know of anyway with out SDK to get the value before the report is rendered but I'll check with

Dan, he may know of a way.

What you may have to do is query the DB first using the SQL from the Report and then dump that data into a Dataset and determine what the values are... Indexing should work but sorting will also have an effect....

Line in BOLD below is where you get the value from the field, but this is the current value indexed by the mouse event...

private void crystalReportViewer1_DoubleClickPage(object sender, PageMouseEventArgs e)

{

    // do not edit this works

    CrystalDecisions.ReportAppServer.ClientDoc.ISCDReportClientDocument rptClientDoc;

    rptClientDoc = rpt.ReportClientDocument;

    //DateTime dtStart;

    //dtStart = DateTime.Now;

    //btnSQLStatement.Text += "\nReport End time: \n" + dtStart.ToString();

    rptClientDoc.ReportOptions.ConvertNullFieldToDefault = true;

    rptClientDoc.ReportOptions.ConvertOtherNullsToDefault = true;

    btnReportObjects.Text = "";

    int t = 0;

    if (e.ObjectInfos != null)

    {

        foreach (ObjectInfo oi in e.ObjectInfos)

        {

            try

            {

                if (oi.ObjectType.ToString() != "GroupChart")

                {

                    if (oi.ObjectType.ToString() != "OleObject")

                    {

                        if (oi.ObjectType.ToString() != "CrossTab")

                        {

                            // This is the field you double clicked on, in the viewer

                            if (oi.Name == e.ObjectInfo.Name)

                                btnReportObjects.Text += @">>> SELECTED OBJECT - you clicked on<<<\n";

                            btnReportObjects.Text += "DataContext: " + oi.DataContext.ToString() + "\n";

                            btnReportObjects.Text += "GroupNamePath: " + oi.GroupNamePath.ToString() + "\n";

                            btnReportObjects.Text += "Hyperlink: " + oi.Hyperlink.ToString() + "\n";

                            string textBox1 = String.Empty;

                            foreach (FormulaField resultField in rptClientDoc.DataDefController.DataDefinition.FormulaFields)

                            {

                                CrystalDecisions.ReportAppServer.ReportDefModel.ReportObjects FormulaFldobjs;

                                FormulaFldobjs = rptClientDoc.ReportDefController.ReportObjectController.GetReportObjectsByKind(CrReportObjectKindEnum.crReportObjectKindField);

                                t = rptClientDoc.DataDefController.DataDefinition.FormulaFields.FindIndexOf(resultField);

                                CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject objField;

                                objField = (CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject)FormulaFldobjs[t];

                                CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject objField2 = (CrystalDecisions.ReportAppServer.ReportDefModel.FieldObject)objField.Clone(true);

                                if (oi.Name.ToString() == objField2.Name.ToString())

                                {

                                    btnReportObjects.Text += "Name: " + oi.Name.ToString() + " -> " + objField2.DataSourceName.ToString() + "\n";

                                }

                                t++;

                            }

                            //btnReportObjects.Text += "Name: " + oi.Name.ToString() + "\n";

                            btnReportObjects.Text += "Value: " + oi.Text.ToString() + "\n";

                            btnReportObjects.Text += "ObjectType: " + oi.ObjectType.ToString() + "\n";

                            btnReportObjects.Text += "Tooltip: " + oi.ToolTip.ToString() + "\n";

                            btnReportObjects.Text += "========================\n";

                            //btnReportObjects.Text += richTextBox1;

                            btnReportObjects.AppendText("\n\n");

                        }

                    }

                }

            }

            catch (Exception ex)

            {

                MessageBox.Show("ERROR: " + ex.Message);

            }

        }

    }

}

If Dan and I can't find a way I'll ping the Developers to see if we can expose any collection that may be what you are looking for. But the problem is until the report is ran you can't get the values because the FormatEngine needs to handle the data dynamically and all formatting comes into effect.

Thanks again

Don

Former Member
0 Kudos

Hi Don,

I'm currently using the FormatSection event, which is on the ReportDocument itself, not the viewer.  So unfortunately the example you have given is not relevant as the ObjectInfos collection is not available from this event.

That said, the FormatSection event is called during the rendering process, so I would assume the FormatEngine must have the values from the database by this time, for the section being rendered..  This is certainly how it used to work in versions of Crystal prior to .Net.  So I think the missing link is the ability to obtain the field values from the ReportObject (fieldObject) either during rendering (FormatSection event) or even after rendering (AfterFormatPage event).  Prior to .Net the IFieldObjectPtr had a Value property which you could access during the Format event, but this property has now been removed.  So if you do talk to the developers it would be worth asking why this was removed and whether it can be put back.

I think you're right though, that grouping/sorting etc will mean that even if I query for the data and put it in a dataset, I'll still have no way to correlate any given section to a row in the dataset.

Okay I'll await your response on how to access the field data during / after the format events, and also why this was removed from the FieldObject in the move to .Net. 

Thanks

Paul

0 Kudos

Hi Paul,

Sorry been busy on an escalation from a paid case which take priority....

Here's part of the code to use:

void crDoc_SectionFormatEvent(CrystalDecisions.CrystalReports.Engine.FormatSectionEventArgs e)

{

    MessageBox.Show("Section format event - " + e.SectionCode.ToString());

    // add code here to get the field name and data

}

private void FieldMapping_Click(object sender, EventArgs e)

{

    //CrystalReport1 crDoc = new CrystalReport1();

    EventEnabledArgs eeArgs = new EventEnabledArgs ();

          

    rpt.FieldMapping += new FieldMappingEventHandler(crDoc_FieldMapping);

    rpt.FormatSection += new FormatSectionEventHandler(crDoc_FormatSection);

    rpt.FormatSection += new FormatSectionEventHandler(crDoc_SectionFormatEvent);

    eeArgs.FormattingEnabled = true;

    rpt.EnableEvent(eeArgs);

}

I have not had time to see if there is a way to get the value yet though.

Don

Former Member
0 Kudos

Thanks Don,  I'm already using the SectionFormat event.  That's wired up fine and I can see the SectionCode in the event args.  That code doesn't correlate to the sections in the ReportDefintion (in CR XI it used to be an index into the ReportDefinition->Sections but not any more), but I have managed to work around that by creating a map of SectionCode to section index by iterating through the ReportClientDocument->ReportDefController->ReportObjectController->GetAllReportObjects().

So from within the SectionFormat event I know which section object is being rendered/formatted, that's ok.  What I can't figure out is how to get the value for each object in the section.

Thanks

Paul

0 Kudos

Hi Paul,

Dan and I both tried to get the value from the field on the event trigger and we can't find a way to do it either. We can get it after the report has ran from the viewer but not while it's running....

All I can suggest now is you log case within SMP and let Kevin know the case number and I'll escalate this to DEV as an Enhancement request and try to get it into SP 17 due out in 3 months...

We don't know if they can get the value at runtime, we'll know more once the case gets escalated to DEV and they look into it to see if there is a way to do it.

Don

0 Kudos

Hi Paul,

Did you log a case? I have not heard about the ER for the SDK.

It won't happen unless you do... We need a Business Case to submit with the request.

Thanks again

Don

0 Kudos

Good day Paul,

I've create a BOSAP case for the Enhancement Request:

Incident 203850 / 2016 / ER - Getting field values for each sect

Because it is an ER it may take some time to implement but DEV now has the case and will begin looking into the process and if they can make it work for you.

Don

0 Kudos

FYI, the case was created and DEV is looking into adding this Enhancement request.

Also, another request for same functionality:

Don

0 Kudos

Hi Paul,

R&D had a deep dive into this Enhancement Request and after their research they determined they will not be able to impliment this functionality.

The issue is we don't allow hooking into the Pre-formating events and therefore there is no backend mechanism to do so.

I can suggest that you change your logic some and predefine those Objects and possibly use the Formatting Condition formula to do the sizing etc. The size could be saved in the DB as a field, if it's not done that way already, and those values could be used to set the OLE Object size and position.

You can do this all before the report is rendered but you will need to provide the info before the report starts to generate.

Thank you again

Don

ido_millet
Active Contributor
0 Kudos

You can use a Crystal UFL to materialize a resize the blob to an image file (on the fly) and feed that into the graphic location property expression. 

One of the UFLs listed at Formula Function Libraries (UFLs) can do this.

0 Kudos

Hi Ido,

Ah, good suggestion, I never thought about using a UFL to get the properties....

Thanks again

Don

Answers (0)