Use PowerShell
The Shell Is Calling
The Shell Is Calling
I’m updating Crystal Reports and trying to determine which reports might have been affected by some schema changes or functional changes in how the data was being stored.
The problem I’ve had is that when there are a large number of reports, it is very time consuming to open each one, look at it, and see if it contains any affected tables or views.
I’ve had to deal with this in my previous role as well. After feeling the pain a few times, I turned my intern loose on the problem and shelved the problem as “just another pain in dealing with Crystal Reports”.
Now, I’m back dealing with Crystal Reports more frequently and in the position to have to possibly update around 30 or 40 reports that were written before I started.
I’ve recently had a bit of exposure to the object model for the .NET API for Crystal Reports and thought maybe I could leverage that through PowerShell and whip together a quick script to help me list out the tables in each report.
It turned out to be painfully easy…
[reflection.assembly]::LoadWithPartialName('CrystalDecisions.Shared') [reflection.assembly]::LoadWithPartialName('CrystalDecisions.CrystalReports.Engine') $report = New-Object CrystalDecisions.CrystalReports.Engine.ReportDocument $report.load($pathToScript) $report.Database.Tables | Select-Object -expand Name $report.Dispose()
After I got the basics, I poked around and updated the script further (and posted it on PoshCode).
The full script also accesses the first level of subreports and retrieves their tables as well.
NOTE: Requires either the Crystal Report Runtime (Visual Studio 2008) or Visual Studio to be installed.
January 7, 2010 - 11:35 am
Thanks, Steven, this is exactly what I was trying to figure out during our last data model change. It’s definitely time for me to check out the .Net API for Crystal Reports and learn PowerShell!
January 7, 2010 - 11:41 am
Glad you found it useful. Let me know if you run in to any questions. I’ve been monkeying with the script a bit further as well (I should post the update later today.)
May 1, 2010 - 8:50 am
I am new to ps. we have hundreds of crystal reports currently kicked off by different platforms, such as crystal enterprise and java. we are looking for a solution to run all reports from 1 source, and is it possible to do it with ps? Is ps able to query sql tables so that we can pass values to crystal parameters? If so, can you please direct me where to start? can you please recommend some books or references? Thanks.
September 28, 2010 - 8:32 pm
Steven,
I’m wrestling a little with which versions of the runtimes and CR Engines I need for this script, plus trying to learn powershell at the same time. I thought I was being smart by downloading VS2010 express, until I saw SAP’s CR .Net Engine is only released for versions up to VS2008.
I’ve discovered my work machine can only support Powershell v1 (it’s got XP SP2), but I can run Powershell v2 at home. Will the Get-CrystalReportTable script possibly run on v1 or does it use features that only v2 support?
Thank you for the explanations!
September 29, 2010 - 5:16 am
Becky,
The script was based on the VS2008 Crystal Reports runtime.
The Get-CrystalReportTable script was written to support version 2 of PowerShell but we could strip out the V2 specific items and the basics of the script will still work. If you are interested, I can post a V1 compatible script.
September 29, 2010 - 12:23 pm
Steven,
That would be fantastic! I could follow the script logic but wasn’t fluent enough in Powershell to know which parts were based on v2 compared to v1. I should be able to get the VS2008 Crystal Reports runtime on my work machine now that we’ve upgraded some of our environment to SQL Server 2008.
Becky
September 29, 2010 - 3:26 pm
There is a new link at the bottom of the post that has a link to a V1 version of the script. I’ve commented out the V2 features and it should work that way. One change is that it is now not pipeline aware.. it will require a path to be provided as a parameter (so if you were piping a directory full of reports to the command it would now look like
dir *.rpt | foreach-object {get-crystalreporttable -path $_.fullname}
Good luck!
October 5, 2010 - 10:52 am
I found your script a perfect starting point for what I’m trying to accomplish. Document all tables and fields in .rpt files.
While I’ve managed to do that, I’m still stuck on one issue. My script finds all fields a table uses instead of just the ones used in the report (you know the ones with the little checkmark with them in CR).
Here’s the code I used to do that
function Get-CRTablesFields()
{
[cmdletbinding()]
param (
[parameter(ValueFromPipelineByPropertyName=$true,Mandatory=$true)]
[Alias('fullname')]
[string]$Path
)
begin
{
[reflection.assembly]::LoadWithPartialName(‘CrystalDecisions.Shared’) | Out-Null
[reflection.assembly]::LoadWithPartialName(‘CrystalDecisions.CrystalReports.Engine’) | Out-Null
}
process
{
try
{
$report = New-Object CrystalDecisions.CrystalReports.Engine.ReportDocument
$report.load($path)
$fname = Split-Path $path -Leaf
$results = $report.database.tables | select Fields
foreach ($line in $results)
{
foreach ($field in $line.fields)
{
$tbl = $field | Select TableName
$fld = $field | Select FormulaName
$aline = $fname + “`t” + $tbl + “`t” + $fld
write-output $aline
}
}
}
finally
{
$report.dispose()
}
}
}
If anyone knows where these fields that are only used in the report are hidden, please let me know.
Also, it is time consuming to explore all of the namespace for possible locations of this information. Does anyone know how to write a recursive get-member the behaves like get-childitem -recurse?
March 9, 2011 - 2:26 pm
Hi Steven,
I’m relatively new to Powershell and a complete Crystal Reports newbie. I’ve been tasked with writing a script to run a folder full of .rpts, export the results to excel, then email the results based on a .rtf (Geeze, why not something HARD?)
I’m stuck on figuring out what the .X is to get the report’s query, and how to pass parameters into a report. If you could point me in the right direction, I’d be eternally grateful. This was a great post and has helped me a bit but I could use one more nudge. Thank you in advance.
July 17, 2011 - 9:08 pm
Yeah, I’ve this one. You can connect your report to almost any data source, as well as to proxy data, such as a result set (for example, an ADO.NET DataSet). The wizards that are included in the GUI designer make it easy to format, group, chart, and present data.