Write Excel file from rdl/rdlc file in Windows application - c++

I have rdl files made by Report Builder 3.0. I need to use them in my Windows application written in C++ in way so that I am able to set SQL Server connection parameters and Report location at runtime.
Is this possible and how?
Google told me that I need to convert rdl to rdlc file, but even then I couldn't find a way of setting these parameters and calling rdlc file from C++.

You can use ReportViewer and use RDL or RDLC files but RDL could have some limitations since it doesn't include necessary information to create data-binding code.
RDL files do not contain some information that the design-time of the
ReportViewer control depends on for automatically generating
data-binding code. By manually binding data, RDL files can be used in
the ReportViewer control.
You can set the parameters from ReportViewer, check this documentation and the below code example in C#:
private void SetReportParameters() {
// Set Processing Mode
reportViewer1.ProcessingMode = ProcessingMode.Remote;
// Set report server and report path
reportViewer1.ServerReport.ReportServerUrl = new
Uri("http://<ServerName>/reportserver");
reportViewer1.ServerReport.ReportPath =
"/AdventureWorks Sample Reports/Employee Sales Summary";
List<ReportParameter> paramList = new List<ReportParameter>();
paramList.Add(new ReportParameter("EmpID", "288", false));
paramList.Add(new ReportParameter("ReportMonth", "12", false));
paramList.Add(new ReportParameter("ReportYear", "2003", false));
this.reportViewer1.ServerReport.SetParameters(paramList);
// Process and render the report
reportViewer1.RefreshReport();
}
This is an example of ReportViewer usage to generate Excel files:
protected void Button1_Click(object sender, EventArgs e)
{
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string extension;
byte[] bytes = ReportViewer1.LocalReport.Render(
"Excel", null, out mimeType, out encoding,
out extension,
out streamids, out warnings);
FileStream fs = new FileStream(#"c:\output.xls",
FileMode.Create);
fs.Write(bytes, 0, bytes.Length);
fs.Close();
Label1.Text = "Report exported to output.xls";
}
Let me know if this can help you.

Related

Create a .zip folder and add files to it in C++ MFC

I am working on an C++ MFC project and one step is to create a large zip file with many other files inside it which may have different paths
As of right now, I have a vector that correctly stores all the file paths as CStrings to each file I will need to collect and add to the zip file
The way I am thinking to tackle this is by creating an empty zip file in a specified folder such as: C:\foo1\foo2\foo3 . The zip file would be titled foo4.zip, so its path would be C:\foo1\foo2\foo3\foo4
Then I would add each file one at a time by iterating through the vector containing the file paths with a for loop
Is it possible to create an empty zip file and add files to it ? If so, how ? Or should I create a regular folder, add files to it, then zip the folder after storing all files ? Or maybe I could create a zip file while supplying it the vector or file paths ?
Which is the better option in which situation and how do I accomplish this in C++ MFC ?
I have done some research on the ZipFile Class in Microsoft's Online Documentation but from my understanding, this Class expects all the files to be zipped to be in the same folder, but in my situation, these files are scattered across many different folders.
I use the ZipArchive library which is freely available here:
https://www.artpol-software.com/
It has excellent help documentation (via download) and you can create zips, add files to zips etc and has full progress monitoring support.
Used it for several years. Later on I will update my answer with sample code.
Single File
try
{
rZipArchive.AddNewFile(strFile, CZipCompressor::levelDefault, false);
}
catch (CZipException* e_)
{
const gsl::not_null<CZipException*> e{ e_ };
e->ReportError();
AfxMessageBox(e->GetErrorDescription(), MB_OK | MB_ICONERROR);
e->Delete();
}
Multiple Files
rZipArchive.AddNewFiles(strFullPath, strFileSpec, false, CZipCompressor::levelDefault, false);
Creating the Zip
Admittedly I have not included the progress callback class as it is fairly easy to write and would be bespoke to your application.
But this code gives you a flavour of what you can do:
try
{
// Create archive and set basic details
zipArchive.Open(strBackupPath, CZipArchive::zipCreate);
zipArchive.SetGlobalComment(_T("xxx"));
zipArchive.SetRootPath(theApp.GetWorkingPath());
/* ================================================ */
CMultiProgressCallback callback;
callback.SetProgressCtrl(&m_ProgressBackupRestore);
callback.SetProgressTextWnd(GetDlgItem(IDC_STATIC_PROGRESS_FILENAME));
callback.SetProgressPercentTextWnd(&m_lblProgressBackupRestore);
zipArchive.SetCallback(&callback,
CZipActionCallback::cbMultiAdd | CZipActionCallback::cbCalculateForMulti);
zipArchive.AddNewFile(strRegPath, CZipCompressor::levelDefault, false);
/* ================================================ */
// Build group filter
ZipArchiveLib::CGroupFileFilter groupFilter;
// Files to include
groupFilter.Add(std::make_unique<ZipArchiveLib::CNameFileFilter>(_T("*.*")).release());
// Files to exclude
groupFilter.Add(std::make_unique<ZipArchiveLib::CNameFileFilter>(_T("exp*.htm"), true).release()); // Preview in Browser
groupFilter.Add(std::make_unique<ZipArchiveLib::CNameFileFilter>(_T("mwe*.xml"), true).release()); // Meeting Workbook Editor
groupFilter.Add(std::make_unique<ZipArchiveLib::CNameFileFilter>(_T("mwp*.xml"), true).release()); // Meeting Workbook Print
groupFilter.Add(std::make_unique<ZipArchiveLib::CNameFileFilter>(_T("sre*.xsl"), true).release()); // Sound Rota Editor
groupFilter.Add(std::make_unique<ZipArchiveLib::CNameFileFilter>(_T("srt*.xsl"), true).release()); // Sound Rota Temp
groupFilter.Add(std::make_unique<ZipArchiveLib::CNameFileFilter>(_T("gcal_*.tmp"), true).release()); // Google Calendar Temp
groupFilter.Add(std::make_unique<ZipArchiveLib::CNameFileFilter>(_T("*.bin3"), true).release()); // Outlook OAuth Cache
zipArchive.AddNewFiles(theApp.GetWorkingPath(), groupFilter, false, CZipCompressor::levelDefault, false);
/* ================================================ */
/* ================================================ */
// AJT v20.1.7 — Backup mode
if (eBackupWhat == COtherSettingsAutomaticBackupPage::EnumBackupWhat::Complete)
{
// Reset
groupFilter.Clear();
// Files to include
groupFilter.Add(std::make_unique<ZipArchiveLib::CNameFileFilter>(_T("*.*")).release());
// Files to exclude
groupFilter.Add(std::make_unique<ZipArchiveLib::CNameFileFilter>(_T("exp*.htm"), true).release()); // Preview in Browser
groupFilter.Add(std::make_unique<ZipArchiveLib::CNameFileFilter>(_T("mwa*.xml"), true).release()); // Meeting Workbook Assignment slips
zipArchive.AddNewFiles(theApp.GetWorkingPath() + _T("AssignmentSlips"),
groupFilter, // Files to include
true, // Recursive
CZipCompressor::levelDefault, // Compression level
false); // Skip initial path
}
/* ================================================ */
auto zipCloseResult = zipArchive.Close();
}
catch (CZipException* e_)
{
const gsl::not_null<CZipException*> e{ e_ };
zipArchive.Close(CZipArchive::afAfterException);
e->ReportError();
bExported = false;
e->Delete();
}
catch (CException *e_)
{
const gsl::not_null<CException*> e{ e_ };
zipArchive.Close(CZipArchive::afAfterException);
// Problem - tell user
e->ReportError();
bExported = false;
e->Delete();
}
if (bExported)
AfxMessageBox(IDS_STR_SETTINGS_SAVED, MB_OK | MB_ICONINFORMATION);
}
The ZipArchive library does have a commercial version where you pay for a license but in my case I did not need to purchase one. This is what it says:
The open source version of the ZipArchive Library is licensed under GNU GPL.
When you download the library you need to build the right version to create your required LIB or DLL for use with your application. Several Visual Studio platform files are provided. Just pick the one you need.

VSIX how to get current snapshot document name?

I have been trying to to create an extension that highlights specific line numbers for me in Visual Studio in the margins.
I manged to get my marking in the margins using predefined line number but for it to work properly I need to know what the current document FullName is (Path and filename)
After much googling I figured out how to do it with the sample code (which is not ideal)
DTE2 dte = (DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.15.0");
var activeDocument = dte.ActiveDocument;
var docName = activeDocument.Name;
var docFullName = activeDocument.FullName;
Now I know the problems here
is that is for specific version bases on the text
there is no way to select which instance (when running more than one VS)
It seems to be very slow
I have a feeling I should be doing this with MEF Attributes but the MS docs examples are so simple that they do not work for me. I scanned a few SO questions too and I just cannot get them to work. They mostly talk about Services.. which I do not have and have no idea how to get.
The rest of my code uses SnapshotSpans as in the example Extension of Todo_Classification examples which is great if you do NOT need to know the file name.
I have never done any extensions development. Please can somebody help me do this correctly.
You can use following code to get a file from a snapshot without any dependencies.
public string GetDocumentPath(Microsoft.VisualStudio.Text.ITextSnapshot ts)
{
Microsoft.VisualStudio.Text.ITextDocument textDoc;
bool rc = ts.TextBuffer.Properties.TryGetProperty(
typeof(Microsoft.VisualStudio.Text.ITextDocument), out textDoc);
if (rc && textDoc != null)
return textDoc.FilePath;
return null;
}
If you don't mind adding Microsoft.CodeAnalysis.EditorFeatures.Text to your project it will provide you with an extension method Document GetOpenDocumentInCurrentContextWithChanges() on the Microsoft.VisualStudio.Text.Snapshot class. (Plus many other Rosyln based helpers)
using Microsoft.CodeAnalysis.Text;
Document doc = span.Snapshot.GetOpenDocumentInCurrentContextWithChanges();

Creating a pst file using Redemption

I'm working on a project in C# that involves parsing .pst files and my group has chosen to use the Redemption library to do so. We have successfully parsed the email files in to RDOMail objects, however now we want to write a subset of those emails to a new .pst file. I have successfully written the subset to .eml files using the email.SaveAs() function, but I'm at a loss to figure out how to save that list as a .pst. I've been sifting through the documentation, however it leaves much to be desired. Can anyone who has used Redemption point me in the right direction or provide an example?? Thanks in advance for your help!
You will need to create/open a PST file using RDOSession.Stores.AddPstStore (returns RDOPSTStore object). Once you have the store, you can open/create folders (starting with the RDOStore.IPMRootFolder), create messages (RDOFolder.Items.Add) and copy old messages into new messages (RDOMail.CopyTo(RDOMail/RDOFolder)).
I have been struggling to do this for the last few hours and would like to save that time to others
You have to install redemption and add it as a reference to your project for it to work
RDOSession session = new RDOSession(); // throws exception 1
session.LogonPstStore(#"c:\temp\output.pst");
RDOFolder folder = session.GetDefaultFolder(rdoDefaultFolders.olFolderInbox);
string[] fileEntries = Directory.GetFiles(#"C:\emlFiles\", "*.eml");
foreach (string filePath in fileEntries)
{
RDOMail mail = folder.Items.Add("IPM.Mail");
mail.Sent = true;
mail.Import(filePath, 1024);
// folder.Items.Add(mail);
mail.Save();
}
session.Logoff();
I also created a small sample windows forms app for it, I know the code is ugly but it does the trick

How to open XML file with Excel?

I want to develop a small tool which for open XML file and launch Excel automatically.
The benefit for user who could save the excel file to .xls format very conveniently.
My Dev IDE: Windows XP pro & Visual Studio 2005.
The tool will running at Windows 2000 & Excel 2000. and there is no .net framework installed.
That means i can't code with C#. My choice is C++.
Oneliner:
int main() {
system("Start Excel test.xml");
}
If I recall correctly you want to open an excel file and then auto launch xml editor?
A way is to add a option the the contect menu when rightclicking on the xls file.
Use register for this:
HKEY_CLASSES_ROOT.xls\shell\
create a key (Default) and value something like "Open excel and xml editor"
create a folder "command" and a key (Default) with value "path to your exe" "%L" in that folder.
Then in your app catch the param (which holds the xls)
and then do something like this:
system(<var holding the xls name>);
system(<path to xml editor>):
You could use ShellExecute. It will automatically start program which associated with certain extension, or you could select program manually.
In C#
OpenXML in MSDN - http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.workbooks.openxml(v=office.11).aspx
using Excel = Microsoft.Office.Interop.Excel;
string workbookPath= #"C:\temp\Results_2013Apr02_110133_6692.xml";
this.lblResultFile.Text = string.Format(#" File:{0}",workbookPath);
if (File.Exists(workbookPath))
{
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = true;
Excel.Workbook excelWorkbook = excelApp.Workbooks.OpenXML(workbookPath, Type.Missing, Excel.XlXmlLoadOption.xlXmlLoadPromptUser);
}
else
{
MessageBox.Show(String.Format("File:{0} does not exists", workbookPath));
}

Use a MSHFlexGrid with non-database data and still define the shape

I am trying to use the Microsoft Hierarchical FlexGrid (MSHFlexGrid) in a Visual C++ (VS 2005). I have the grid shown, and I can manually add data to the individual cells. However, according to online documentation I've read, I should be able to show the hierarchical nature of the data (hence MSHFlexGrid instead of MSFlexGrid) by defining the SHAPE as the RecordSource. I can do that fine (by using the put_RecordSource method of the grid object), however I'm at a loss as to how to add the actual data.
I've read that the best way to do this is to use an ADO Data Control (ie ADODC) component and bind it as the DataSource for the Grid. You can then specify "provider=msdatashape;data provider=none;" as the provider of the DataControl and fill it with data. If I were doing SQL, I'd specify my SELECT query as the RecordSource, then call Refresh() and let the control load the data.
However, my data is in custom objects. I know what needs to be displayed, I'm just at a loss as to the best way to insert the data into the FlexGrid and still use the built in features of the control. I'm open to any suggestions, but I need to keep the data local (ie no JET, Access, etc).
Here's some code:
In header:
....
// Variable to control the Flex Grid component
CMshflexgrid1 m_grid; //generated by wizard from the MSHFlexGrid component
// to control the data source hierarchical information
CAdodc1 m_adodc1;
....
In cpp:
....
BOOL MyDialogClass::OnInitDialog()
{
CDialog::OnInitDialog();
m_grid.Clear();
CString strCn = "provider=msdatashape;data provider=none;";
m_adodc1.put_ConnectionString(strCn);
CString BackupOfRecordSource = "";
BackupOfRecordSource = m_adodc1.get_RecordSource();
//CString strShape = "SHAPE APPEND new adInteger As PID, New adVarChar(10) As StudentName, ((SHAPE APPEND new adInteger As ChID, New adVarChar(10) As Course, ((SHAPE APPEND new adInteger As GrndChID, New adBSTR As Description) RELATE ChID TO GrndChID) As GrandChild) RELATE PID TO ChID) AS Child";
CString strShape = "SHAPE APPEND new adInteger As PID, New adVarChar(10) As StudentName";
m_adodc1.put_RecordSource(strShape);
m_adodc1.Refresh();
m_grid.Refresh();
BackupOfRecordSource = m_adodc1.get_RecordSource(); //returns the strShape that I just put in
//ADD RECORDS HERE! HOW?
return TRUE;
}
The sample talked about building an ADODB.Recordset and use it as the data source of ADODC. The code you give is building a SQL and use it as the data source of ADODC. I don't think you can replace an ADODB.Recordset with a string.