In SSRS there is a report property called Author.
I am attempting to display the author at the bottom of my report in a text box. I tried the following:
="Report Created By " & Globals!Author
But it didn't work. Please let me know what I am missing here.
I do not think this data is exposed in th report builder, however, If you want to maintain a custom assembly and embed it in your report then you can take the code below and add to be called by your report's custom code.
Create class library project that references Microsoft.SqlServer.ReportingServices2010 similar to below.
using RS = Microsoft.SqlServer.ReportingServices2010;
public class MicrosoftReportingService //: IReportService
{
private RS.ReportingService2010 _service=new RS.ReportingService2010();
public void CheckConnection()
{
_service.Url = <SSSR_ENPOINT>;
NetworkCredential credentials = new NetworkCredential(<USER_NAME>,<PASSWORD>,<DOMAIN>);
_service.Credentials=credentials;
}
private List<RS.CatalogItem> GetReportsInFolder(string path)
{
CheckConnection();
RS.CatalogItem[] reportItems = _service.ListChildren(path, true);
List<RS.CatalogItem> result = new List<RS.CatalogItem>();
foreach (RS.CatalogItem reportItem in reportItems)
if (reportItem.TypeName == "Report" || reportItem.TypeName == "LinkedReport")
result.Add(reportItem);
return result;
}
public CatalogItem GetReportData(string reportPath, string reportName)
{
List<RS.CatalogItem> reportItems = GetReportsInFolder(reportPath);
return reportItems.Where(p=>p.Name==reportName).FirstOrDefault();
}
public string GetReportAuthor(string reportPath, string reportName)
{
CatalogItem item = GetReportData(reportPath,reportName);
return (item == null) ? "" : item.CreatedBy;
}
}
Include the assembly in your report.
Once the assembly is on the report server and referenced by your report then you can create a wrapper function in the report custom code similar to:
Public GetReportAuthor(reportPath As String, reportName As String) As String
Dim rs As New MicrosoftReportingService()
Return rs.GetReporAuthor(reportPath, reportName)
End Procedure
Finally, you can embed the code into an expression.
lblAuthor = Code.GetReportAuthor(<REPORT_PATH>,<REPORT_NAME>)
Related
I've implemented an IMvxNavigationFacade for deep linking in my MvvmCross 5.6.x sample app. I've added logic in BuildViewModelRequest() to construct a MvxViewModelRequest with parameters passed in as MvxBundle.
if (url.StartsWith("http://www.rseg.net/rewards/"))
{
var parametersBundle = new MvxBundle();
var id = url.Substring(url.LastIndexOf('/') + 1);
parametersBundle.Data.Add("id", id);
return Task.FromResult(
new MvxViewModelRequest(typeof(RewardDetailViewModel),
parametersBundle, null));
}
However, this approach causes the old style Init() method to be called in the target ViewModel rather than the new typesafe Prepare() method.
public class RewardDetailViewModel :
MvxViewModel<RewardDetailViewModel.Parameteres>
{
...
public new void Init(string id)
{
if (!string.IsNullOrWhiteSpace(id))
{
if (int.TryParse(id, out _rewardId))
RaiseAllPropertiesChanged();
}
}
public override void Prepare(Parameteres parameter)
{
if (parameter != null)
{
_rewardId = parameter.RewardId;
RaiseAllPropertiesChanged();
}
}
}
Is there a way to construct a MvxViewModelRequest so that you pass in an instance of the parameter class for the target ViewModel causing the Prepare() method to be called?
The entire solution can be viewed on GitHub https://github.com/rsegtx/So.MvvmNav2
Thanks in advance!
After doing some research I found at lease one way to accomplish this.
Create a ViewModelInstanceRequest rather than a ViewModelRequest so that you can call ViewModelLoader.LoadViewModel passing in a parameters object; the ViewModelRequest only allows parameters to be passed using a MvxBundle. Make the following change to BuildViewModelRequest() on the NavigationFacade:
var request = new
MvxViewModelInstanceRequest(typeof(RewardDetailViewModel));
var parameters = new RewardDetailViewModel.Parameteres();
.... parse parameters and fill in parameters object
request.ViewModelInstance = ViewModelLoader.LoadViewModel(
request, parameters, null);
return Task.FromResult((MvxViewModelRequest)request);
Create your own IMvxNavigationService and add logic to inspect the object returned from the NavigationFacde and if it is a ViewModelInstanceRequest then use it as is rather than one previously creating.
var facadeRequest = await facade.BuildViewModelRequest(path,
paramDict).ConfigureAwait(false);
...
if (facadeRequest is MvxViewModelInstanceRequest)
request = facadeRequest as MvxViewModelInstanceRequest;
else
{
facadeRequest.ViewModelType = facadeRequest.ViewModelType;
if (facadeRequest.ParameterValues != null)
{
request.ParameterValues = facadeRequest.ParameterValues;
}
request.ViewModelInstance = ViewModelLoader.LoadViewModel(
request, null);
}
I've updated the original example on GitHub https://github.com/rsegtx/So.MvvmNav2.
I'm trying send a set of query results in an email using SSIS. Below is the screen shot and steps for the flow.
Screenshot:
Steps:
1. Using SQL task to get the results of the query in "queryresult" object variable
2. Using the "queryresult" object variable in the Foreach loop and getting the column Values in the string variables "ProjectRefID" and "Accountnumber"
3.Using script task inside the foreachloop container to capture the data in the object variable "query result"
Below is the code inside the script task which I copied from the internet.
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
endregion
namespace ST_77e6b4ea18824b909adc5568475fcf5c
{
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
public void Main()
{
Variables varCollection = null;
string header = string.Empty;
string message = string.Empty;
Dts.VariableDispenser.LockForWrite("User::ValidationEmailMessage");
Dts.VariableDispenser.LockForRead("User::Accountnumber");
Dts.VariableDispenser.LockForRead("User::ProjectRefID");
Dts.VariableDispenser.GetVariables(ref varCollection);
if (varCollection["User::ValidationEmailMessage"].Value == string.Empty)
{
header = "Below are the list of Invalid ProjecRefID and Accountnumbers that are not matching with our existing data:\n\n";
header += string.Format("{0}\t{1}\t\t\t{2}\n", "ProjectRefID", "Accountnumber");
varCollection["User::ValidationEmailMessage"].Value = header;
varCollection.Unlock();
}
//Format the query result with tab delimiters
message = string.Format("{0}\t{1}\t{2}",
varCollection["User::ProjectRefID"].Value,
varCollection["User::Accountnumber"].Value);
varCollection["User::ValidationEmailMessage"].Value = varCollection["User::ValidationEmailMessage"].Value + message;
varCollection.Unlock();
Dts.TaskResult = (int)ScriptResults.Success;
}
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
}
}
I tried to resolve this error but somehow I'm not able to figure this out. Let me know if anyone knows how to resolve it.
Unless you require the locking functionality for some reason, you should be able to write the Main method simply as this:
public void Main()
{
string header = string.Empty;
string message = string.Empty;
if (Dts.Variables["User::ValidationEmailMessage"].Value == string.Empty)
{
header = "Below are the list of Invalid ProjecRefID and Accountnumbers that are not matching with our existing data:\n\n";
header += string.Format("{0}\t{1}\t\t\t{2}\n", "ProjectRefID", "Accountnumber");
Dts.Variables["User::ValidationEmailMessage"].Value = header;
}
//Format the query result with tab delimiters
message =
string.Format("{0}\t{1}\t{2}",
Dts.Variables["User::ProjectRefID"].Value,
Dts.Variables["User::Accountnumber"].Value);
Dts.Variables["User::ValidationEmailMessage"].Value = Dts.Variables["User::ValidationEmailMessage"].Value + message;
Dts.TaskResult = (int)ScriptResults.Success;
}
Also, with your string.Format code, you are specifying three indexes, {0}, {1} and {2}, yet you are only providing 2 arguments, i.e. , "ProjectRefID", "Accountnumber");.
I want to query the hide/show status of parameters of a report. But it seems there is no property that tells that.
I used reporting service 2010, not reportviewer control. http://msdn.microsoft.com/en-us/library/reportservice2010.itemparameter.aspx
Below is my code:
public class ReportingService
{
private ReportingService2010 reportingService = null;
public ReportingService()
{
reportingService = new ReportingService2010();
reportingService.Credentials = CredentialCache.DefaultCredentials;
}
internal IList<ReportParameter> GetReportParameter(string reportUrl)
{
string historyId = null;
bool forRendering = false;
ParameterValue[] values = null;
DataSourceCredentials[] credentialses = null;
ItemParameter[] parameters = null;
try
{
parameters = reportingService.GetItemParameters(reportUrl, historyId, forRendering, values, credentialses);
foreach (var parameter in parameters)
{
//parameter.Name;
//parameter.Prompt;
//parameter.DefaultValues.FirstOrDefault();
//Problem:
//how to get the show/hide status of the parameter.
//the PromptUser returns true only when both hide and prompt
//are false, but when hide is true, it return true.
//The rdl is edited via IE. It can be also edited via BI, and others.
}
return reportParameters;
}
catch (SoapException e)
{
throw;
//e.Detail.InnerXml.ToString();
}
}
}
Any idea would be very much appreciated!
private bool IsShown(ItemParameter parameter)
{
return parameter.PromptUser && !string.IsNullOrEmpty(parameter.Prompt);
}
From here:
There is no "Hidden" property that you can check directly. Rather,
you need to look at both the Prompt and PromptUser properties on the
ReportParameter class:
PromptUser == false --> Parameter is "Internal"
PromptUser == true && Prompt is null or empty --> Parameter is
"Hidden"
PromptUser == true && Prompt is NOT null or empty --> Parameter is
visible
Did you check the parameter.Visible property? Will that work?
Basically I've written a C# script for a Script task in SSIS that looks in a User::Directory for 1 csv, if & only if there is one file, it stores that in the instance variable which then maps to the package variables of SSIS.
When I exicute, it gives me the red filled in box of the Script task. I think it's related to how I'm looking at the directory, but I'm not sure.
Please help!
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.IO;
namespace ST_e8b4bbbddb4b4806b79f30644240db19.csproj
{
[System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
private String fileName = "";
private String RootDirictory;
private String FilePath;
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
public ScriptMain()
{
RootDirictory = Dts.Variables["RootDir"].Value.ToString();
FilePath = RootDirictory + "\\" + "SourceData" + "\\";
}
public void setFileName()
{
DirectoryInfo YDGetDir = new DirectoryInfo(FilePath);
FileInfo[] numberOfFiles = YDGetDir.GetFiles(".csv");
if (numberOfFiles.Length < 2)
{
fileName = numberOfFiles[0].ToString();
}
int fileNameLen = fileName.Length;
String temp = fileName.Substring(0, fileNameLen - 5);
fileName = temp;
}
public void mapStateToPackage()
{
if((fileName!=null)||(fileName!=""))
{
Dts.Variables["ExDFileName"].Value = fileName;
}
}
public void Main()
{
setFileName();
mapStateToPackage();
Dts.TaskResult = (int)ScriptResults.Success;
}
}
}
This could simply be done using Foreach loop container as explained in this Stack Overflow question, which was asked by you. :-)
Anyway, to answer your question with respect to Script Task code that you have provided. Below mentioned reasons could be cause of the issues:
You are looking for .csv. This won't return any results because you are looking for a file with no name but extension .csv. The criteria should be *.csv
If you are looking for exactly one file, then the condition if (numberOfFiles.Length < 2) should be changed to if (numberOfFiles.Length == 1)
The section of code after the if section which extracts the file name should be within the above mentioned if condition and not out side of it. This has to be done to prevent applying substring functionality on an empty string.
Modified code can be found under the Script Task Code section.
Sorry, I took the liberty to simplify the code a little. I am not suggesting this is the best way to do this functionality but this is merely an answer to the question.
Hope that helps.
Script Task Code:
C# code that can be used only in SSIS 2008 and above.
/*
Microsoft SQL Server Integration Services Script Task
Write scripts using Microsoft Visual C# 2008.
The ScriptMain is the entry point class of the script.
*/
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.IO;
namespace ST_3effcc4e812041c7a0fea69251bedc25.csproj
{
[System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
Variables varCollection = null;
String fileName = string.Empty;
String fileNameNoExtension = string.Empty;
String rootDirectory = string.Empty;
String filePath = string.Empty;
#region VSTA generated code
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
#endregion
public void Main()
{
Dts.VariableDispenser.LockForRead("User::RootDir");
Dts.VariableDispenser.LockForWrite("User::ExDFileName");
Dts.VariableDispenser.GetVariables(ref varCollection);
rootDirectory = varCollection["User::RootDir"].Value.ToString();
filePath = rootDirectory + #"\SourceData\";
DirectoryInfo YDGetDir = new DirectoryInfo(filePath);
FileInfo[] numberOfFiles = YDGetDir.GetFiles("*.csv");
if (numberOfFiles.Length == 1)
{
fileName = numberOfFiles[0].ToString();
fileNameNoExtension = fileName.Substring(0, fileName.LastIndexOf("."));
}
if (!String.IsNullOrEmpty(fileNameNoExtension))
{
varCollection["User::ExDFileName"].Value = fileNameNoExtension;
}
Dts.TaskResult = (int)ScriptResults.Success;
}
}
}
I'm working with MS Reporting Services. The underlying datasource is
IEnumerable<MyObject>, I'm not using DataSets.
Every MyObject has properties and some other IEnumerable collections.
In the report I want to display all the properties from MyObject and
the collections lists too.
I didn't know how to display this inner collections, so I've made a SubReport to which I passed the MyObject.Id so that the SubReport could retrieve the object by himself and Build a the DataSource for these inner collections.
I do this in this event.
myReportViewer.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
private void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
{
int id;
if (e.Parameters.Count > 0 && int.TryParse(e.Parameters[0].Values[0], out id))
{
MyObject current = myObjects.Where(x => x.MyObject.Id == id).FirstOrDefault();
InnerListBindingSource.DataSource = current.InnerCollection;
e.DataSources.Add(new Microsoft.Reporting.WinForms.ReportDataSource(
"MyInnerCollectionDataSource", InnerListBindingSource));
}
}
But there is always "The SubReport could not be shown" in my Master Report.
(Master report - subreport are correctly binded)
Any Idea why? Or how to resolve this in a more elegant way ?
Thank you
OK.
So I went to this solution and it's working:
private IEnumerable<MyObject> myObjects;
public ReportViewerForm(IEnumerable<MyObject> myObjects)
{
InitializeComponent();
this.myObjects = myObjects;
this.WindowState = FormWindowState.Maximized;
ReportViewer reportViewer = new ReportViewer();
reportViewer.ProcessingMode = ProcessingMode.Local;
reportViewer.LocalReport.ReportEmbeddedResource = #"SomePath." + "Report1.rdlc";
/*reportViewer.LocalReport.ReportPath = #"SomePath\Report1.rdlc"; */
reportViewer.LocalReport.SubreportProcessing +=
new SubreportProcessingEventHandler(SubreportProcessingEventHandler);
reportViewer.LocalReport.DataSources.Add(
new ReportDataSource("MyDataSource", myObjects));
reportViewer.LocalReport.SetParameters(new List<ReportParameter>
{
new ReportParameter("param1", ..WhatEver..),
...
});
reportViewer.Dock = DockStyle.Fill;
this.panel1.Controls.Add(reportViewer);
reportViewer.RefreshReport();
}
void SubreportProcessingEventHandler(object sender, SubreportProcessingEventArgs e)
{
/* For example ID parsing.. when you have it defined in .rdlc file.. */
int id;
if (e.Parameters.Count > 0 && int.TryParse(e.Parameters[0].Values[0], out id))
{
MyObject current = myObjects.Where(x => x.MyObject.Id == id).FirstOrDefault();
e.DataSources.Add(new Microsoft.Reporting.WinForms.ReportDataSource(
"InnerListDataSource", current.InnerList));
}
}
If I understand you correctly, you have a structure that resembles a table. So why don't you take a DataTable? ReportingServices offers easy access to those.
Or did I get you wrong there?