Crystal reports drill down issue - crystal-reports

Ok so I made some changes and got somewhere. However the issue is still their. I figured out that when the main report is generated the Hyperlinks are not added to some of the fields. However when we re-run the report again with the same parameter (we have a link that re-runs the report only changing the year parameter) those fields now have links. This is very weird. For an example I run the report for 2012 press the link to go back to 2011 and then press the link to go forward to 2012 the links now work in 2012.

Do you only assign the 'ReportDocument' object to the CrystalReportViewer on the first page load? You should try storing your report document in session and ensure that on postbacks the CrystalReportViewer control's 'ReportSource' property is set again.
if (!IsPostBack)
{
// do a bunch of Crystal Report's loading stuff
ReportDocument yourReportDocument = new ReportDocument();
// etc, etc.
// store the report document in server memory
yourViewerControl.ReportSource = yourReportDocument;
Session["theReportDocument"] = yourReportDocument;
}
else
{
yourViewerControl.ReportSource = Session["theReportDocument"];
yourViewerControl.Show();
}

Related

Issue while adding/updating TOC in MS Word using OpenXML

I have a requirement to add/update TOC - Table of Contents in MS document using OpenXML. I am facing challenges to achieve the same. I am using MS Office 2016.
I have tried all the options from this post:
How to generate Table Of Contents using OpenXML SDK 2.0?
Also gone through Eric White videos.
I am trying to use UpdateField option and able to add empty TOC following the sample code from the above link.
However when I open the document I am not getting a pop-up dialog which will ask to update the TOC.
Here is the sample code:
var sdtBlock = new SdtBlock();
sdtBlock.InnerXml = GetTOC(); //TOC Xml
document.MainDocumentPart.Document.Body.AppendChild(sdtBlock);
DocumentFormat.OpenXml.Wordprocessing.SimpleField f;
f = new SimpleField();
f.Instruction = "sdtContent";
f.Dirty = true;
document.MainDocumentPart.Document.Body.Append(f);
var setting = document.MainDocumentPart.DocumentSettingsPart;
if (setting != null)
{
document.MainDocumentPart.DocumentSettingsPart.Settings.Append(new UpdateFieldsOnOpen() { Val = new DocumentFormat.OpenXml.OnOffValue(true)});
document.MainDocumentPart.DocumentSettingsPart.Settings.Save();
}
It is displaying default message, whereas I have valid entries (Headings).
Is it due to MS Office 2016? UpdateField Pop-up is not coming?
I don't want to go with below options:
Word Automation - Due to Microsoft.Office.Interop.Word
Word Automation Services - Require Sharepoint for this
Adding Macro - As it is asking to save the document every time I open it.
Also let me know if there is any better option to create/update TOC.
Your answer/comment is really very helpful.

How to display modified body after Outlook ItemLoad

I have code to parse emails and add "tel:" links to phone numbers, but the modified email body doesn't get shown in the Outlook Reading Pane until the user manually reloads it (view another email, come back to this one).
I've tried a few hacks like Inspector.Display, and ActiveExplorer.ClearSelection ActiveExplorer.AddToSelection, but I can't get consistent results (Display will open new Inspectors for some users, very undesirable).
I was also going to investigate hooking the event sooner. Somehow accessing the email body before Outlook renders it, to avoid the need to refresh. I'm very new to VSTO, so I don't know what event would have access to the MailItem but happen after a user selects it and before it is rendered. I have thought about only processing new mail, but that doesn't help when I roll out this addin, only going forward.
Here is my current ItemLoad sub:
Private Sub Application_ItemLoad(Item As Object)
Dim myObj As Outlook.MailItem
Dim ob As Object
ob = GetCurrentItem()
If TypeOf ob Is Outlook.MailItem Then
myObj = ob
Dim oldbody As String = myObj.Body
If myObj.HTMLBody.Length > 0 Then
myObj.HTMLBody = RegularExpressions.Regex.Replace(myObj.HTMLBody, "(?<!tel:)(?<![2-9\.])(?<!\>\ )[+]?(1-)?(1)?[\(]?(?<p1>\d{3})[\)]?[\.\- ]?(?<p2>\d{3})[\.\- ]?(?<p3>\d{4})(?=[^\d])", " ${p1}-${p2}-${p3}")
Else
myObj.Body = RegularExpressions.Regex.Replace(myObj.Body, "(?<!tel:)(?<![2-9\.])[+]?(1-)?(1)?[\(]?(?<p1>\d{3})[\)]?[\.\- ]?(?<p2>\d{3})[\.\- ]?(?<p3>\d{4})(?=[^\d])", "tel:${p1}.${p2}.${p3}")
End If
myObj.Save()
refreshCurrentMessage()
End If
End Sub
GetCurrentItem() just returns either objApp.ActiveExplorer.Selection.Item(1) or objApp.ActiveInspector.CurrentItem based on TypeName(objApp.ActiveWindow)
Outlook doesn't reflect changes made through the OOM immediately. You need to switch to another folder/email to get the item refreshed because there is no way to update the item on the fly.
You can use the CurrentFolder property of the Explorer class which allows to set a Folder object that represents the current folder displayed in the explorer. Thus, the view will be switched to another folder. Then you can set the CurrentFolder folder to initial folder.
Also I'd suggest releasing all underlying COM objects instantly. Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object.

SSRS ReportingService2010 change embedded DataSource to shared DataSource

I have SQL Server 2008 with SSRS installed on one server and SQL Server 2008 R2 with SSRS installed on a new server. I want to migrate 200+ reports as well as a few shared schedules and a couple data sources from the first server to the second one using the SSRS web service API. For simplicity sake since there are only a couple of shared data sources I went ahead and created those using the Report Manager interface.
Unfortunately, those who came before me embedded the data source information in each report (connection string, login, password, etc). I thought this would be a great time to change these to point to the shared data source so this would not have to be done for each report, one by one. I can create the reports on the new server just fine using CreateCatalogItem but I can't seem to determine how to properly go about changing from an embedded data source to a shared data source.
So far I have tried both SetItemReferences:
itemRef.Reference = "/Data Sources/TMS";
itemRef.Name = "TMS";
itemRef.Reference = "/Data Sources/TMS";
rs2010.SetItemReferences(catItem.Path, new ReportService2010.ItemReference[] { itemRef });
and SetItemDataSources:
ReportService2010.DataSourceReference dataSourceRef = new ReportService2010.DataSourceReference();
dataSourceRef.Reference = "/Data Sources/TMS";
ReportService2010.DataSource dataSource = new ReportService2010.DataSource();
dataSource.Name = "TMS";
dataSource.Item = dataSourceRef;
rs2010.SetItemDataSources(catItem.Path, new ReportService2010.DataSource[] { dataSource });
Both methods result in a "NotFoundException" when attempted on a report with an embedded data source but they both work just fine on reports that are already pointing to a shared data source.
Furthermore, I have searched all over Google as well as StackOverflow for a solution but have found nothing. Can anyone point me in the right direction here?
So I kept working with the SetItemReferences method and had a brilliant idea that ended up working. The final code I used is below:
List<ReportService2010.ItemReference> itemRefs = new List<ReportService2010.ItemReference>();
ReportService2010.DataSource[] itemDataSources = rs2010.GetItemDataSources(catItem.Path);
foreach (ReportService2010.DataSource itemDataSource in itemDataSources)
{
ReportService2010.ItemReference itemRef = new ReportService2010.ItemReference();
itemRef.Name = itemDataSource.Name;
itemRef.Reference = "/Data Sources/TMS";
itemRefs.Add(itemRef);
}
rs2010.SetItemReferences(catItem.Path, itemRefs.ToArray());
The problem was that I was not using the same DataSource name as what was found in the report .rdl file. I was able to determine what the name should be using the GetItemDataSources method. Since this method returns an array and may have more than one item in said array, I looped through it to create multiple ItemReferences if more than one existed though I doubt that happens very often if at all.

Getting data from crystal report parameter field

Greetings.
I have a parameter field in my crystal report called job. When i'm calling this report from web page, it prompts me for an input value ("Job1" or "Job2"). After i choose one, it displays in report. But when i try to export report to MS Word with
crystalReport.ExportToDisk(ExportFormatType.WordForWindows, "C:\\foo.doc");
i'm getting "Parameter value is missing" exception.
If i'm setting value manually with
crystalReport.SetParameterValue("job", value);
everything works fine, but i don't need to set a value manually. I want to use a value, chosen in crystal report prompt.
How can this be done?
Are you using a webform or a winform?
If you are using a webform make sure that you initialize ,load, set parameter of the reports on each postback.
private void ShowReport_click()
{
..do initializing,loading,provide logoninfo for data access, provide parameters
... show report
}
private void buttonExport_click()
{
ShowReport_click();
...Your Export Logic goes here
}
same can be applied to winforms too.

How do you detect and print the current drilldown in the CrystalReportViewer control?

When using Business Objects' CrystalReportViewer control, how can you detect and manually print the report the user has currently drilled into? You can print this automatically using the Print() method of the CrystalReportViewer, but I want to be able to do a manual printing of this report.
It is possible to print the main ReportSource of the CrystalReportViewer, but I need to know what report the user has drilled into and then do a manual printing of that particular drill down. Any ideas?
I'm not sure which version of Crystal Reports you are using, but if it is XIR2 or earlier then this isn't possible. I haven't used the newer versions so I can't tell you. One thing that I've done to solve this in the past was to have the drill actually link to another report altogether. It depends on how your viewers actually view the reports (either via a thick-client viewer, the developer, or the web portal) on whether this will work however. Good luck!
detect: yes!
webpage:
<CR:CrystalReportViewer ...
ondrill="CrystalReportViewer1_Drill"
ondrilldownsubreport="CrystalReportViewer1_DrillDownSubreport" />
code behind:
protected void CrystalReportViewer1_Drill(object source, CrystalDecisions.Web.DrillEventArgs e)
{
//drill from graph to list of elements
}
protected void CrystalReportViewer1_DrillDownSubreport(object source, CrystalDecisions.Web.DrillSubreportEventArgs e)
{
//drill from main report to subreports
}
print current: no!
protected void CrystalReportViewer1_DrillDownSubreport(object source, CrystalDecisions.Web.DrillSubreportEventArgs e)
{
reportDocument.OpenSubreport(e.NewSubreportName).ExportToHttpResponse(format, Response, true, title);
}
exporting subreports throws an exception "not allowed for subreports".
solution
CrystalReportsViewer's button works also on drilldown...
<CR:CrystalReportViewer HasExportButton="true" ....