How to use Crystal Report in FsXaml - f#

I have added Report.rpt and a Report.fs file by right clicking on project in Solution Explorer. In Report.fs I have declared two Type Report() and CachedReport(), which in C# are generated automatically, and added F# code in it by looking at a .cs file which CrystalReport generated in a C# WPF Projet. In Xaml I have
<ContentControl Content="{Binding ShowReport}"/>
<Button Command="{Binding ViewReport}" Content="Click" Grid.Row="1"/>
and in ViewModel
let doc = new CrystalReportsViewer()
let setSource() =
let rpt = new Report()
rpt.Load("~/Report.rpt")
doc.ViewerCore.ReportSource <- rpt
member x.ShowReport = doc
member x.ViewReport = self.Factory.CommandSync(setSource)
When I start the application I can see CrystalReport Viewer in place. If I click the button Application closes automatically.
If I double click on Report.rpt a dialog box pops up and says This document could not be opened.
How can I use it in F# WPF?
Is there any other reporting tool for F# WPF?

I just need to build a C# Class Library with a Report as embedded resource, add the assembly in F# reference and write ...
let doc = new CrystalReportsViewer()
let setSource() =
let rpt = new MyCsClass.CrystalReport1()
....
doc.ViewerCore.ReportSource <- rpt
thats all!

Related

How to pass parameter to the table's datasource with Telerik Reporting?

I have a table on my Telerik report where I want to pass parameters with the table's data source. I also have a report datasource with parameter but this does not help with the table's datasource and its parameter. Any help would be appreciated.
this.table1.DataSource = "GetLocationsData";
You have to set the available values source and most probably filters:
Telerik.Reporting.ReportParameter reportParameter1 = new Telerik.Reporting.ReportParameter();
this.csvDataSource1 = new Telerik.Reporting.CsvDataSource();
this.table1 = new Telerik.Reporting.Table();
this.csvDataSource1.Source = "id,text\r\n1,a\r\n2,b\r\n3,c";
this.table1.DataSource = this.csvDataSource1;
this.table1.Filters.Add(new Telerik.Reporting.Filter("= Fields.text", Telerik.Reporting.FilterOperator.Equal, "= Parameters.paramString.Value"));
reportParameter1.AvailableValues.DataSource = this.csvDataSource1;
reportParameter1.AvailableValues.ValueMember = "=Fields.Text";
reportParameter1.Name = "paramString";
reportParameter1.Text = "String";
reportParameter1.Value = "a";
reportParameter1.Visible = true;
this.ReportParameters.Add(reportParameter1);
If this does not help you, you can have a look at the available reports that come with the installation - replace in the path below your Telerik Reporting version, mine is R3 2022. View Code (F7) on the report's designer.cs file:
C:\Program Files (x86)\Progress\Telerik Reporting R3 2022\Examples\CSharp\.NET Framework\ReportLibrary
Another option if you are stuck, is to create the report in the Visual Studio Designer and View the generated code (F7) on the yourreportname.designer.cs file.
If the report was created using the web report or standalone report designer you can import the report definition file (trdp, trdx, trbp) into Visual Studio (will be converted to type definition .cs file) first.
Reference:
https://docs.telerik.com/reporting/designing-reports/connecting-to-data/report-parameters/how-to-add-report-parameters
https://docs.telerik.com/reporting/designing-reports/connecting-to-data/report-parameters/overview

MVC5 with ReportViewerForMvc

I am designing an MVC application using ReportViewerForMVC. This is my controller code:
ReportViewer rp = new ReportViewer();
rp.ProcessingMode = ProcessingMode.Local;
rp.LocalReport.ReportPath = Request.MapPath(Request.ApplicationPath)
+ #"Report/sampleFile.rdlc";
ViewBag.ReportViewer = rp;
This is my View:
#using ReportViewerForMvc
#Html.ReportViewer(ViewBag.ReportViewerMicrosoft.Reporting.WebForms.ReportViewer)
The iframe shows but i get this message:
A data source instance has not been supplied for the data source 'DataSet1'.
as my output for the report section. I thought i specified my data source when designing my .rdlc file.
Again, i want to ask if i create a datatable with a where clause having parameter, how can i specify the value in my controller.
I have searched online and i'm not getting any useful. Can anyone please help me out?
The report viewer has no DataSource. If you like using designer view like myself, you could start by creating a dataset and adding a dataAdapter which will automatically add a dataTable. The dataSource can be set like this:
DataSet1 ds = new DataSet1();
TableAdapter1 ta = new TableAdapter1();
ta.Fill(ds.Table[0]);
ReportDataSource rds = new ReportDataSource();
rds.Name = "DataSet";
rds.Value = ds.Table[0];
rp.LocalReport.DataSources.Clear();
rp.LocalReport.DataSources.Add(rds);
rp.LocalReport.Refresh();
As simple as that...
Change the following in View
#Html.ReportViewer(ViewBag.ReportViewerMicrosoft.Reporting.WebForms.ReportViewer)
to
#Html.ReportViewer(ViewBag.ReportViewer as Microsoft.Reporting.WebForms.ReportViewer)

Open a picture (jpg.) in F#

I would like to open several pictures (.jpg) with F#.
All my pictures are stored in afile (filepath). I would like to show them to the user.
How can I do this using F#?
To open one picture, it tried something like :
open System.IO
let editPicture filepath =
let fileStream = File.Open(filepath,FileMode.Open)
fileStream.Visible <- True
but it doesn t work.
Here is a minimal quick and dirty WinForms F# snippet that shows a .jpg image on a screen:
open System
open System.Windows.Forms
open System.Drawing
let form = new Form()
let pb = new PictureBox()
pb.Image <- Image.FromFile(path-to-file-with-your-jpg-image)
pb.SizeMode <- PictureBoxSizeMode.AutoSize
form.Controls.Add(pb)
[<STAThread>]
do
Application.Run(form)
This may give you some initial traction and feel on what is involved into reaching your goal. But overall I agree with Carsten König that learning curve for doing UIs with F# is quite steep.

ADODBCould not load type 'ADODB.FieldsToInternalFieldsMarshaler' from assembly

I'm trying to read an ADOBD.Recordset object like this (my first time, so pardon my "noobness" :D):
Presentation.Category categorySvc = new Presentation.Category();
ADODB.Recordset categories = categorySvc.ListAll("BE", "DUE", "EN", 128);
foreach (var category in categories.Fields) // here is where I get the exception
{
// ...
}
The ListAll call works fine - I get the Recordset with some data which I confirm that by doing a QuickWatch on the object. But when the code reach the categories.Fields I get the following exception:
Could not load type
'ADODB.FieldsToInternalFieldsMarshaler'
from assembly 'TestCOMCalls,
Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null'.
I googled this error (or just by 'ADODB.FieldsToInternalFieldsMarshaler' and couldn't find anything that would help me with issue).
I wonder, am I missing a reference? Besides the normal references I have added this one to my project:
ADODB
Microsoft ActiveX Data Objects 2.5 Library
C:\WINDOWS\assembly\GAC\ADODB\7.0.3300.0__b03f5f7f11d50a3a\ADODB.dll
Like I said, I've never done this before but by googling a bit I was able to see some people doing this (foreach on the object.Fields) and it seem to work for them.
Any help or direction is greatly appreciated :)
Thanks!
It's on the individual references - not in the project properties. In the solution explorer window, open "References" (under the project), and click on the reference in question. The properties window will have an option for Embed Interop Types (for each reference).
In Visual BAsic 2010:
To turn off Embed Interop Types:
Project menu > Show All Files, Solution Explorer: > References: > ADODB > Embed Interof types = False. Microsoft.Office.Interop.Access > Embed Interof types = False
You will now be able to publish and also ADODB will appear in the: Project Menu > Project Properties… Publish TAB > Application Files
Solved:
Solution Explorer --> Show all files (Menu Item) --> Referances --> Adodb -->(properties) -->Embed Interop Types --> False.
See what I found on this question here. I referenced yours, but still couldn't get the ADODB to work.
Little one to add:
SolutionExplorer --> View All Files.
For ADODB:
- Embed... = False;
- Copy Local = True.
Got the same problem in VS 2013, and the solution for that is that you go to
References and select ADODB, on properties you will see Embed Interof types = True then change it to false.
I got this problem clearing temporary file(VS 2017). Solution for this exception you need to change Solution Explorer > References > adodb > "Then Right click and choose properties" > Embed Interop Types, set "True" to "False"
Okay, I figured how to do this:
Presentation.Category categorySvc = new Presentation.Category();
ADODB.Recordset categories = categorySvc.ListAll("BE", "DUE", "EN", 128);
categories.MoveFirst();
while(!categories.EOF)
{
var fields = ((dynamic)categories).Fields;
for (int i = 0; i < fields.Count; i++)
{
var field = fields[i];
var name = field.Name;
var value = field.Value;
// ...
}
categories.MoveNext();
}

Unable to append a sheet using OpenXml with F# (FSharp)

The CreateSpreadsheetWorkbook example method from the OpenXml documentation does translate directly to F#. The problem seems to be the Append method of the Sheets object. The code executes without error, but the resulting xlsx file is missing the inner Xml which should have been appended, and the file is unreadable by Excel. I suspect the problem stems from the conversion of functional F# structures into a System.Collections type, but I do not have direct evidence for this.
I have run similar code in C# and VB.NET (i.e. the documentation example) and it executes perfectly and creates a readable, complete xlsx file.
I know that I could deal with the XML directly, but I would like to understand the nature of the mismatch between F# and OpenXml. Any suggestions?
The code is almost directly from the example:
namespace OpenXmlLib
open System
open DocumentFormat
open DocumentFormat.OpenXml
open DocumentFormat.OpenXml.Packaging
open DocumentFormat.OpenXml.Spreadsheet
module OpenXmlXL =
// this function overwrites an existing file without warning!
let CreateSpreadsheetWorkbook (filepath: string) =
// Create a spreadsheet document by supplying the filepath.
// By default, AutoSave = true, Editable = true, and Type = xlsx.
let spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook)
// Add a WorkbookPart to the document.
let workbookpart = spreadsheetDocument.AddWorkbookPart()
workbookpart.Workbook <- new Workbook()
// Add a WorksheetPart to the WorkbookPart.
let worksheetPart = workbookpart.AddNewPart<WorksheetPart>()
worksheetPart.Worksheet <- new Worksheet(new SheetData())
// Add Sheets to the Workbook.
let sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets())
// Append a new worksheet and associate it with the workbook.
let sheet = new Sheet()
sheet.Id <- stringValue(spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart))
//Console.WriteLine(sheet.Id.Value)
sheet.SheetId <- UInt32Value(1u)
// Console.WriteLine(sheet.SheetId.Value)
sheet.Name <- StringValue("TestSheet")
//Console.WriteLine(sheet.Name.Value)
sheets.Append (sheet)
// Console.WriteLine("Sheets: {0}", sheets.InnerXml.ToString())
workbookpart.Workbook.Save()
spreadsheetDocument.Close()
The sheet is created, but empty:
sheet.xml:
<?xml version="1.0" encoding="utf-8" ?>
<x:worksheet xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" />
workbook.xml:
<?xml version="1.0" encoding="utf-8" ?>
- <x:workbook xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
- <x:sheets>
<x:sheet name="TestSheet" sheetId="1" r:id="R263eb6f245a2497e" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" />
</x:sheets>
</x:workbook>
The problem is very subtle, and is in your calls to the Worksheet constructor and the Sheets.Append method. Both of these methods are overloaded, and can take either a seq<OpenXmlElement> or any number of individual OpenXmlElements (via a [<System.ParamArray>]/params array). The twist is that the OpenXmlElement type itself implements the seq<OpenXmlElement> interface.
In C#, when you call new Worksheet(new SheetData()), the compiler's overload resolution picks the second of the overloads, implicitly creating a one-element array containing the SheetData value. However, in F#, since the SheetData class implements IEnumerable<OpenXmlElement>, the first overload is chosen, which creates a new WorkSheet by enumerating the contents of the SheetData, which is not what you want.
To fix this, you need to set up your calls so that they use the other overload (first example below) or explicitly create a singleton sequence (second example below):
worksheetPart.Worksheet <- new Worksheet(new SheetData() :> OpenXmlElement)
...
sheets.Append([sheet :> OpenXmlElement])

Resources