Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Ñlosing reports during run-time (CRDC 8.5 & VC++ 6.0)

Status
Not open for further replies.

demask

Programmer
Nov 21, 2002
2
GB
Hi.

I have a problems with closing reports during run-time using Crystal Report Designer Component (RDC) from
Crystal Repotrs 8.5 with Visual C++ 6.0. I have the following member variables defined in my appilication CWinApp-derived
class:

IApplicationPtr m_pApplication;
IReportPtr m_pReport;
IFieldObjectPtr m_pobjDetail[3]; // fields pointers array for three objects
ITextObjectPtr m_pobjHeader[3]; // text pointers array for three objects
ITextObjectPtr m_pobjFooter; // fields pointer for report footer
CCrystalReportViewer4* m_pCryst;
CAdodc m_ctlADODC; // Microsoft ADO Data Control

At application startup I'm initializing m_pApplication and creating CCrystalReportViewer4 object:

...

m_pApplication.CreateInstance("CrystalRuntime.Application");
m_pCryst=new CCrystalReportViewer4;

...

After that I'm creating ADO Data Control window. When user selects a new database, I'm setting new
ADO record source and creating new report during run-time at the following manner:

ISectionPtr pSection,pHeaderSection,pFooterSection;
ISectionPtr pGroupSection;

...

// get reference to my ADO recordset
CAdodc& refADO=m_ctlADODC;
C_Recordset& rc=refADO.GetRecordset();

// creating a new report (***)
m_pReport=m_pApplication->NewReport();

// add database to a report (THE REASON OF MY HEADACHE)
m_pReport->Database->Tables->Add("",vTemp,_variant_t((IDispatch *)rc.m_lpDispatch,true),vTemp,"p2smon.dll");

// get the Detail section using "D" and Header section using "PH" as the index
pSection=m_pReport->Sections->GetItem("D");
pHeaderSection=m_pReport->Sections->GetItem("PH");
pFooterSection=m_pReport->Sections->GetItem("PF");

// add data to the report's Header section
m_pobjHeader[0]=pHeaderSection->AddTextObject("Field1",400,0);
m_pobjHeader[1]=pHeaderSection->AddTextObject("Field2",1100,0);
m_pobjHeader[2]=pHeaderSection->AddTextObject("Field3",2900,0);

// add data to the report's Detail section
m_pobjDetail[0]=pSection->AddFieldObject("{ado.Field1}",400,0);
m_pobjDetail[1]=pSection->AddFieldObject("{ado.Field2}",1100,0);
m_pobjDetail[2]=pSection->AddFieldObject("{ado.Field3}",2900,0);

// add data to the report's Footer section
_bstr_t bstrMessage("My report footer");
m_pobjFooter=pFooterSection->AddTextObject(bstrMessage,0,0);
::SysFreeString(bstrMessage);

// pass the report to the viewer and preview the report
m_pCryst->SetReportSource(NULL);
m_pCryst->SetReportSource(m_pReport);
m_pCryst->Zoom(100);
m_pCryst->ViewReport();

...

Above code works fine and I can see a valid report.
When user closes current database, I'm trying to close ADO recordset and report:

C_Recordset& rc=m_ctlADODC.GetRecordset();
if (rc.m_lpDispatch!=NULL) rc.Close(); // close recordset if it wasn't closed previously

// destroy footer since it doesn't refresh
pSection=m_pReport->Sections->GetItem("D");
pHeaderSection=m_pReport->Sections->GetItem("PH");
pFooterSection=m_pReport->Sections->GetItem("PF");
for (int j=0;j<3;j++) {
if (m_pobjHeader[j]!=NULL) pHeaderSection->DeleteObject(_variant_t(& *m_pobjHeader[j]));
if (m_pobjDetail[j]!=NULL) pSection->DeleteObject(_variant_t(& *m_pobjDetail[j]));
m_pobjHeader[j]=NULL; m_pobjDetail[j]=NULL;
}
if (m_pobjFooter!=NULL) pFooterSection->DeleteObject(_variant_t(& *m_pobjFooter));
m_pobjFooter=NULL;

// destroy report data
j=m_pReport->Database->Tables->GetCount();
while (j) {
m_pReport->Database->Tables->Delete(j);
j--;
}
m_pCryst->SetReportSource(NULL);
m_pCryst->DestroyWindow();
m_pReport->Release(); // HERE IS I'V GOT AN ERROR. HOW CAN I CLOSE OR
m_pReport=NULL; // DISCONNECT REPORT FROM ADO RECORDSET PROPERLY
// TO PREVENT DATABASE FROM STAYING LOCKED?

When I comment the last string (&quot;m_pReport=NULL;&quot;), the database stay locked and the error appear
during recreating report at line commented with &quot;***&quot; (&quot;m_pReport=m_pApplication->NewReport();&quot;).
Could anybody advise how can I destroy created report properly (since there is no such method as
CloseReport at IApplicationPtr, or related method) to reuse the m_pReport for the next report and
prevent database from staying locked? Thank you very much!

P.S. Where can I get entire documentation on Crystal Report Designer Component (RDC)?

 
I have not used the viewer but has used ADO to give data to a Crystal Report and then printed it. Perhaps you can use some of my code. Note that I still have a problem with memory leakage when I print several times so the code is not complete...
******************************************
Urk2002.h:

// For ADO recordset
#import &quot;msado15.dll&quot; no_namespace rename(&quot;EOF&quot;, &quot;EndOfFile&quot;)

// For Crystal Reports:
#import &quot;craxdrt.dll&quot; no_namespace rename(&quot;IArea&quot;, &quot;ICrystalArea&quot;) rename(&quot;IAreaPtr&quot;, &quot;ICrystalAreaPtr&quot;) rename(&quot;IApplicationPtr&quot;, &quot;ICrystalApplicationPtr&quot;) rename(&quot;Application&quot;, &quot;CrystalApplication&quot;)

class CUrk2002App : public CWinApp
{
public:
CUrk2002App();

CODBC *m_OODBC;
IApplicationPtr pApplication; // Crystal Reports application object
IReportPtr pReport; // Crystal Reports report object

AlarmEvent.cpp:

void CAlarmEventView::OnButtonPrint()
{
int nRow = 0; // row in grid
int nRecord = 0; // record/messages with data from structure
int nRecords = 0;
int nStartIdx = 0;
int nRecordsToShow = 0;


// Define ADO object pointers. Initialize pointers on define.
_RecordsetPtr pRstAlarms = NULL;
_ConnectionPtr pConnection = NULL;

FieldsPtr pFldLoop = NULL;
PropertiesPtr pPrpLoop = NULL;
_variant_t vtIndex;
vtIndex.vt = VT_I2;

HRESULT hr = S_OK;

// The Report->Open() function requires two null arguments.
// We'll create a variant that ADO will recognize as a null.
_variant_t vNull;
vNull.vt = VT_ERROR;
vNull.scode = DISP_E_PARAMNOTFOUND;

// Definer et recordset
TESTHR(pRstAlarms.CreateInstance(__uuidof(Recordset)));

SetCursor(LoadCursor(NULL, IDC_WAIT));

nRecords = m_nRecordsAlarms;
nStartIdx = m_nStartIndexAlarms;

if( nRecords == 0)
return;

if( m_nRbutShowAll == 0) // Show all
{
nStartIdx = 0;
nRecordsToShow = nRecords;
}
else // Show 1000
{
if( nStartIdx < 0 )
nStartIdx = 0;

if( nStartIdx > nRecords )
nStartIdx = 0;

// Set upper limit to 1000 above or max records
nRecordsToShow = nStartIdx + RECORDS_TO_SHOW;

if( nRecordsToShow > nRecords )
{
nRecordsToShow = nRecords;
}
}

// *** Add columns to the recordset ***
_bstr_t strColName(&quot;date&quot;);
pRstAlarms->Fields->Append(strColName, adChar, 20, adFldUpdatable);

strColName = &quot;rtag&quot;;
pRstAlarms->Fields->Append(strColName, adChar, 20, adFldUpdatable);

strColName = &quot;descr_tag&quot;;
pRstAlarms->Fields->Append(strColName, adChar, 100, adFldUpdatable);

strColName = &quot;event&quot;;
pRstAlarms->Fields->Append(strColName, adChar, 40, adFldUpdatable);

strColName = &quot;aslabel&quot;;
pRstAlarms->Fields->Append(strColName, adChar, 15, adFldUpdatable);

pRstAlarms->Open(vNull, vNull, adOpenForwardOnly,adLockOptimistic, adCmdText);

// *** Fetch all data into recordset ****
for( nRecord = nStartIdx; nRecord < nRecordsToShow; nRecord++ )
{
// Sett inn verdi for første kolonne
_variant_t varFieldList(&quot;date&quot;);
_variant_t varFieldValues = (_bstr_t)m_ptDataAlarms[nRecord].szTimeStamp;

// Legger til en ny rad til recordsettet med verdi i første kolonne
pRstAlarms->AddNew( varFieldList, varFieldValues);

// Legg til resten av dataene i denne raden
pFldLoop = pRstAlarms->GetFields();

vtIndex.iVal = 1;
pFldLoop->GetItem(vtIndex)->Value = (_bstr_t)m_ptDataAlarms[nRecord].szTag;

vtIndex.iVal = 2;
pFldLoop->GetItem(vtIndex)->Value = (_bstr_t)m_ptDataAlarms[nRecord].szDescr;

vtIndex.iVal = 3;
pFldLoop->GetItem(vtIndex)->Value = (_bstr_t)m_ptDataAlarms[nRecord].szType;

vtIndex.iVal = 4;
pFldLoop->GetItem(vtIndex)->Value = (_bstr_t)m_ptDataAlarms[nRecord].szSystem;

pRstAlarms->Update();
}

// Åpne forhåndsdefinert Crystal Report
theApp.pApplication.CreateInstance(&quot;CrystalRuntime.Application&quot;);
theApp.pReport = theApp.pApplication->OpenReport(&quot;./alarmevent.rpt&quot;);

// for use in place of optional arguments
VARIANT dummy;
VariantInit(&dummy);
dummy.vt = VT_EMPTY;

// Overfør ADO Recordset til rapporten
theApp.pReport->Database->Tables->GetItem(1)->SetDataSource(_variant_t((IDispatch *)pRstAlarms,true),dummy);

theApp.pReport->PrintOut();

// Clean up objects before exit.
pRstAlarms->Close();
theApp.pReport->Release();
theApp.pReport = NULL;
theApp.pApplication->Release();
theApp.pApplication = NULL;
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top