I'm sure I'm missing somming very small here, but this is really getting to me now.
I have used the SDK to save a report to HTML (and XML), but when I try a format like XLS or PDF, I get text, but not the data I need to write the file and read it in excel or Adobe Acrobat Reader.
If I use the reportrunner sample in the SDK I get the same issue.
My testing code (I know it's messy) below (strongly based on SDK)...
public bool GetReportSDK(string inCogID, string inSaveAs, ExportFormat inExpForm, string inUserName, string inPassword, string inNamespace)
{
bool retVal = false;
string strFormat = "";
if(inExpForm == ExportFormat.PDF)
{
strFormat = "PDF";
inSaveAs += ".pdf";
}
else if(inExpForm == ExportFormat.XLS)
{
strFormat = "singleXLS";
inSaveAs += ".xls";
}
try
{
CognosConnection cogConn = new CognosConnection(this.strCogSerrverPath, inNamespace, inUserName, inPassword);
cogConn.Connect();
asynchReply executeReportResponse = null;
option[] arrRunOpts = new option[4];
parameterValue[] arrParm = new parameterValue[] { };
runOptionBoolean blnPromptOption = new runOptionBoolean();
runOptionStringArray outputFormat = new runOptionStringArray();
asynchOptionInt primaryWait = new asynchOptionInt(); // primary wait threshold
string[] strarrFmt = new string[1];
runOptionBoolean blnSaveOption = new runOptionBoolean();
// Specify do not save the output
blnSaveOption.name = runOptionEnum.saveOutput;
blnSaveOption.value = false;
// execute the report in selected format
strarrFmt[0] = strFormat;
outputFormat.name = runOptionEnum.outputFormat;
outputFormat.value = strarrFmt;
// Specify do not prompt for parameters (being passed)
blnPromptOption.name = runOptionEnum.prompt;
blnPromptOption.value = false;
// set the primary wait threshold to 0 seconds - wait indefinitely
primaryWait.name = asynchOptionEnum.primaryWaitThreshold;
primaryWait.value = 0;
// fill the array with the run options
arrRunOpts[0] = blnPromptOption;
arrRunOpts[1] = outputFormat;
arrRunOpts[2] = primaryWait;
arrRunOpts[3] = blnSaveOption;
searchPathSingleObject cmReportPath = new searchPathSingleObject();
cmReportPath.Value = "storeID(\""+ inCogID +"\")";
// execute the report
executeReportResponse = cogConn.C8RS.run(cmReportPath, arrParm, arrRunOpts);
// If response is not immediately complete, call wait until complete
if(!executeReportResponse.status.Equals(asynchReplyStatusEnum.complete))
{
while(!executeReportResponse.status.Equals(asynchReplyStatusEnum.complete))
{
//before calling wait, double check that it is okay
if(!hasSecondaryRequest(executeReportResponse, "wait"))
retVal = false;
executeReportResponse = cogConn.C8RS.wait(executeReportResponse.primaryRequest, new parameterValue[] { }, new option[] { });
}
//After calling wait() it is necessary to check to make sure
//the output is ready before retrieving it
if(outputIsReady(executeReportResponse))
{
executeReportResponse = cogConn.C8RS.getOutput(executeReportResponse.primaryRequest, new parameterValue[] { }, new option[] { });
}
else
retVal = false;
}
executeReportResponse = cogConn.C8RS.render(executeReportResponse.primaryRequest, new parameterValue[] { }, new option[] { });
object objTemp = (object)(asynchDetail)executeReportResponse.details[0];
string strOutputPage = getOutputPage(executeReportResponse);
strLocal = new FileStream(inSaveAs, FileMode.Create, FileAccess.Write, FileShare.None);
byte[] btData = UTF8Encoding.UTF8.GetBytes(strOutputPage);
strLocal.Write(btData, 0, btData.Length);
retVal = true;
}
catch(Exception excp)
{
throw excp;
}
finally
{
if(strLocal != null)
strLocal.Close();
}
return (retVal);
}
Thanks in advance
OK - seems all I needed was to sleep on it. Here's the solution if anyone faces the same problem.
Further reading in the SDK docs, stated something I missed "Base64 encoded"!!!
So, instead of writing the response directly to file, we need to decode it first
Change
byte[] btData = UTF8Encoding.UTF8.GetBytes(strOutputPage);
To
byte[] btData = Convert.FromBase64String(strOutputPage);
Now I can go neaten things up :)