Export to Excel spreadsheet in Cross Platform C# .NET app - c#

So I'm writing a cross platform app that will run on Mac, Linux, and Windows. I need a library that can export to a .xlsx without having to have Excel installed on the host computer. Also, I will need to include simple formulas in the spreadsheet. I'm brand new to .NET so I don't know which version of .NET Core the library should be compatible with in order for the app to be cross platform capable. I've heard of ClosedXML which looks perfect for what I'm trying to do. But absolutely no where on the NuGet page nor on their GitHub page does it state whether it's compatible with .NET Core or cross-platform, etc. Please help! I've written whole programs before only to find out I've written it with the completely wrong tools.

You can try my SwiftExcel library. Besides that it is cross platform (if you install it into your .NET Core application), this library is also very efficient as it writes directly to the file. For example you can write 100k rows in few seconds without any memory usage.
Here is a simple example of usage:
using (var ew = new ExcelWriter("C:\\temp\\test.xlsx"))
{
for (var row = 1; row <= 10; row++)
{
for (var col = 1; col <= 5; col++)
{
ew.Write($"row:{row}-col:{col}", col, row);
}
}
}
You can also use some basic formulas like Count, Max, Sum or Average. Here is an example from the same GitHub page:
using (var ew = new ExcelWriter("C:\\temp\\test.xlsx"))
{
for (var row = 1; row <= 20; row++)
{
ew.Write(row.ToString(), 1, row, DataType.Number);
}
ew.WriteFormula(FormulaType.Average, 1, 22, 1, 1, 20);
ew.WriteFormula(FormulaType.Count, 1, 23, 1, 1, 20);
ew.WriteFormula(FormulaType.Max, 1, 24, 1, 1, 20);
ew.WriteFormula(FormulaType.Sum, 1, 25, 1, 1, 20);
}

When confronted with this, I start with a simple proof of concept application. In your case that would be: Create an .xls file with just a single entry. With such a simple project, it's easy to try out several libraries quickly.
Start by creating a .NET core project, then import a nuget package and see if it still compiles. If it does, great, try and let it run on android instead of windows. If it still runs, great. Now you can start writing the first lines of code where you use the library. Just try to create a .xls with a simple entry. Try it on windows, android. If that works test out if the library has all the functionality you need.
If all that passes you've got something that's probably going to work.
Divide and conquer, always go step by step.

Related

System.Drawing.Common is not supported on this platform - on Windows, VS2019

I am calling a function in my class library project from WorkerService class. Both apps are using .net core 3.1. I am compiling the code locally on Windows 10 and using Visual Studio 2019.
What am I exactly missing here?
Here's my code using PdfSharp
PdfDocument doc = new PdfDocument();
doc.Options.FlateEncodeMode = PdfFlateEncodeMode.BestCompression;
doc.Options.UseFlateDecoderForJpegImages = PdfUseFlateDecoderForJpegImages.Automatic;
doc.Options.NoCompression = false;
doc.Options.CompressContentStreams = true;
Image MyImage = Image.FromFile(imageLocation);
for (int PageIndex = 0; PageIndex < MyImage.GetFrameCount(FrameDimension.Page); PageIndex++)
{
MyImage.SelectActiveFrame(FrameDimension.Page, PageIndex);
XImage img = XImage.FromGdiPlusImage(MyImage);
var page = new PdfPage();
page.Size = PageSize.Letter;
if (MyImage.Width > MyImage.Height)
{
// In case the scanned POD is landscape, rotate the image by 90 degrees
MyImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
page.Rotate = 270;
}
doc.Pages.Add(page);
XGraphics xgr = XGraphics.FromPdfPage(doc.Pages[doc.Pages.Count - 1]);
xgr.DrawImage(img, 0, 0, page.Width, page.Height);
xgr.Dispose();
}
doc.Save(Savepath);
doc.Close();
It is blowing up on this line
Image MyImage = Image.FromFile(imageLocation);
The WHOLE concept of .net core is to reduce, if not outright remove dependances on windows code, and thus it becomes multi-platform, and even quite much CPU "processor" agnostic (allowing .net code to run on your phone, tablet, Linux, or even some small Raspberry device, and you don't even need a Intel/AMD processor for such code to run).
As such, you have to remove your dependences on windows.system.drawing of which PDF sharp uses. In fact, OFTEN using any non .net core library and reference is going to cause you much grief, since any .net library (non core) is going to often cause a dependency on windows.
I believe you can stick to text only, but if you are shoving in graphics, then you have to change your code.
there is a nuget package now here:
https://github.com/ststeiger/PdfSharpCore
It not 100% prime time ready, but some are reporting good success with that library.
A discussion of this issue can be found here:
https://github.com/empira/PDFsharp/issues/6

CATIA V5 C# how to get AxisSystem from Active Document

I'm trying to update XAxis on Active CATIA document using C#. Anyone knows how to do that? somehowGetActiveAxisSysObject() is placeholder in pseudo code:
Array xMatrix = Array.CreateInstance(typeof(double), 3);
xMatrix.SetValue(5.0, 0);
xMatrix.SetValue(0.0, 1);
xMatrix.SetValue(0.0, 2);
MECMOD.AxisSystem targetAxisSys = **somehowGetActiveAxisSysObject();**
targetAxisSys.PutXAxis(xMatrix);
THANK YOU!
It's been a while since I worked with Catia in C# so the code below may not run properly.
First, I will assume you are working in a part document and that you have created an axis system from the menu: Insert->AxisSystems->AxisSystem (or named something similar). Next, I will also assume that you went into this items properties and renamed it to "Larry".
MECMOD.AxisSystems thisPartsAxisSysCollection = (MECMOD.AxisSystems)Part.AxisSystems;
MECMOD.AxisSystem oneAxisSys = thisPartsAxisSysCollection(1); //Index is name unknown
//or
MECMOD.AxisSystem oneAxisSys = thisPartsAxisSysCollection("Larry");
oneAxisSys.PutXAxis("your data");
If this is not what you are trying to do, but instead are trying to move the part's origin then you will need to access Part.OriginElements instead and use that object's PlaneXY, PlaneYZ, and PlaneZX. Unfortunately those are read only if I remember correctly.

Using Python for .NET in VS (C#) I get a file not found exception trying to import numpy

I have been trying and trying to make python.net work in my WPF application. I did a pip install of python.net and reference python.runtime.dll in my VS project. 4/5 of the included embedding tests failed though I couldn't figure out why (EDIT: When run individually they all seem to pass. I'm still suspicious). Here's the most recent code attempt in C#
PythonEngine.Initialize();
PythonEngine.AcquireLock();
PythonEngine.RunSimpleString("import sys\n"); PythonEngine.RunSimpleString("sys.path.append('C:/Users/mhames/AppData/Local/Continuum/Anaconda2/Lib/site-packages')\n");
PyObject np = PythonEngine.ImportModule("numpy");
Everything debugs fine until the last line, which throws a file not found exception. "Additional information: Could not load file or assembly 'numpy' or one of its dependencies. The system cannot find the file specified."
Previously, I've tried the format recommended on the python.net page:
using (Py.GIL())
{
dynamic np = Py.Import("numpy");
dynamic sin = np.sin;
Console.WriteLine(np.cos(np.pi * 2));
Console.WriteLine(sin(5));
double c = np.cos(5) + sin(5);
Console.WriteLine(c);
/* this block is temporarily disabled due to regression
dynamic a = np.array(new List<float> { 1, 2, 3 });
dynamic b = np.array(new List<float> { 6, 5, 4 }, Py.kw("dtype", np.int32));
Console.WriteLine(a.dtype);
Console.WriteLine(b.dtype);
Console.WriteLine(a * b);
*/
Console.ReadKey();
}
But this throws the exact same exception at the attempted numpy import. Before trying to run any python, the WPF application opens a system dialogue for a file selection, which I doubt is affecting anything but I'm desperate at this point. I also have both python 2.7 and python 3 on my computer, my PATH environment variable contains paths for both my versions of Anaconda, but I've also tried adding a specific PYTHONHOME and PYTHONPATH that point to only the python 2.7 folders.
Any ideas are much appreciated at this point.

C# code completion with NRefactory 5

I just found out about NRefactory 5 and I would guess, that it is the most suitable solution for my current problem. At the moment I'm developing a little C# scripting application for which I would like to provide code completion. Until recently I've done this using the "Roslyn" project from Microsoft. But as the latest update of this project requires .Net Framework 4.5 I can't use this any more as I would like the app to run under Win XP as well. So I have to switch to another technology here.
My problem is not the compilation stuff. This can be done, with some more effort, by .Net CodeDomProvider as well. The problem ist the code completion stuff. As far as I know, NRefactory 5 provides everything that is required to provide code completion (parser, type system etc.) but I just can't figure out how to use it. I took a look at SharpDevelop source code but they don't use NRefactory 5 for code completion there, they only use it as decompiler. As I couldn't find an example on how to use it for code completion in the net as well I thought that I might find some help here.
The situation is as follows. I have one single file containing the script code. Actually it is not even a file but a string which I get from the editor control (by the way: I'm using AvalonEdit for this. Great editor!) and some assemblies that needs to get referenced. So, no solution files, no project files etc. just one string of source code and the assemblies.
I've taken a look at the Demo that comes with NRefactory 5 and the article on code project and got up with something like this:
var unresolvedTypeSystem = syntaxTree.ToTypeSystem();
IProjectContent pc = new CSharpProjectContent();
// Add parsed files to the type system
pc = pc.AddOrUpdateFiles(unresolvedTypeSystem);
// Add referenced assemblies:
pc = pc.AddAssemblyReferences(new CecilLoader().LoadAssemblyFile(
System.Reflection.Assembly.GetAssembly(typeof(Object)).Location));
My problem is that I have no clue on how to go on. I'm not even sure if it is the right approach to accomplish my goal. How to use the CSharpCompletionEngine? What else is required? etc. You see there are many things that are very unclear at the moment and I hope you can bring some light into this.
Thank you all very much in advance!
I've just compiled and example project that does C# code completion with AvalonEdit and NRefactory.
It can be found on Github here.
Take a look at method ICSharpCode.NRefactory.CSharp.CodeCompletion.CreateEngine. You need to create an instance of CSharpCompletionEngine and pass in the correct document and the resolvers. I managed to get it working for CTRL+Space compltition scenario. However I am having troubles with references to types that are in other namespaces. It looks like CSharpTypeResolveContext does not take into account the using namespace statements - If I resolve the references with CSharpAstResolver, they are resolved OK, but I am unable to correctly use this resolver in code completition scenario...
UPDATE #1:
I've just managed to get the working by obtaining resolver from unresolved fail.
Here is the snippet:
var mb = new DefaultCompletionContextProvider(doc, unresolvedFile);
var resolver3 = unresolvedFile.GetResolver(cmp, loc); // get the resolver from unresolvedFile
var engine = new CSharpCompletionEngine(doc, mb, new CodeCompletionBugTests.TestFactory(resolver3), pctx, resolver3.CurrentTypeResolveContext );
Update #2:
Here is the complete method. It references classes from unit test projects, sou you would need to reference/copy them into your project:
public static IEnumerable<ICompletionData> DoCodeComplete(string editorText, int offset) // not the best way to put in the whole string every time
{
var doc = new ReadOnlyDocument(editorText);
var location = doc.GetLocation(offset);
string parsedText = editorText; // TODO: Why there are different values in test cases?
var syntaxTree = new CSharpParser().Parse(parsedText, "program.cs");
syntaxTree.Freeze();
var unresolvedFile = syntaxTree.ToTypeSystem();
var mb = new DefaultCompletionContextProvider(doc, unresolvedFile);
IProjectContent pctx = new CSharpProjectContent();
var refs = new List<IUnresolvedAssembly> { mscorlib.Value, systemCore.Value, systemAssembly.Value};
pctx = pctx.AddAssemblyReferences(refs);
pctx = pctx.AddOrUpdateFiles(unresolvedFile);
var cmp = pctx.CreateCompilation();
var resolver3 = unresolvedFile.GetResolver(cmp, location);
var engine = new CSharpCompletionEngine(doc, mb, new CodeCompletionBugTests.TestFactory(resolver3), pctx, resolver3.CurrentTypeResolveContext );
engine.EolMarker = Environment.NewLine;
engine.FormattingPolicy = FormattingOptionsFactory.CreateMono();
var data = engine.GetCompletionData(offset, controlSpace: false);
return data;
}
}
Hope it helps,
Matra
NRefactory 5 is being used in SharpDevelop 5. The source code for SharpDevelop 5 is currently available in the newNR branch on github. I would take a look at the CSharpCompletionBinding class which has code to display a completion list window using information from NRefactory's CSharpCompletionEngine.

Why isn't this code executing correctly (video)?

I'm using Unity (3.4) Monodevelop (2.4.2) and it's not executing the code properly when I step through it in the debugger. Here's a link to the video that shows it, please run it at 720p and fullscreen it...
http://www.youtube.com/watch?v=LGN7kxMUqjA
Also, here are some screenshots showing the debugger displaying really strange values when I mouseover a variable. Here's what it looks like when it correctly shows the value of the xSectionPixel in the first if block...
And here's what it looks like when it incorrectly shows the value of the xSectionPixel in the second if block...
This is also the line of code where it starts executing code incorrectly.
What would cause this?
I've tried reinstalling the tools, using a fresh copy of the code from the repository, I even set it all up on a different computer with a different OS (Win 7) and it always does the same thing. Doesn't that mean it has to be my code then?
It's also worth noting that I'm using SVN to push/pull the code from a repository and my local copy exists in my Dropbox folder.
Thanks so much in advance for your wisdom! Here's the code as well if you can spot anything that might be breaking things (i.e. the way I'm using floats and ints maybe?)
Vector2 textureCoordToHexGridCoord(int textX, int textY)
{
Vector2 hexGridCoord = new Vector2();
float m = hexH / hexR;
int xsection = (int)(textX / (hexH + hexS));
int ysection = (int)(textY / (2 * hexR));
int xSectionPixel = (int)(textX - xsection * (hexH + hexS));
int ySectionPixel = (int)(textY - ysection * (2 * hexR));
//A Section
if(xsection % 2 == 0)
{
hexGridCoord.x = xsection;
hexGridCoord.y = ysection;
if(xSectionPixel < (hexH - ySectionPixel * m))
{
hexGridCoord.x--;
hexGridCoord.y--;
}
if(xSectionPixel < (-hexH + ySectionPixel * m))
{
hexGridCoord.x--;
}
}
//B Section
else
{
if(xSectionPixel >= hexR)
{
if(ySectionPixel < (2 * hexH - xSectionPixel * m))
{
hexGridCoord.x = xsection - 1;
hexGridCoord.y = ysection - 1;
}
else
{
hexGridCoord.x = xsection;
//hexGridCoord.y = ysection;
hexGridCoord.y = ysection - 1;
}
}
if(xSectionPixel < hexR)
{
if(ySectionPixel < (xSectionPixel * m))
{
hexGridCoord.x = xsection;
//hexGridCoord.y = ysection - 1;
hexGridCoord.y = ysection;
}
else
{
hexGridCoord.x = xsection - 1;
hexGridCoord.y = ysection;
}
}
}
return hexGridCoord;
}
I have no specific experience with the frameworks you use, but I do have a lot of experience with debuggers.
The debugger behavior you see can happen in one of two scenarios (that I can think of...)
The symbol files and executing code are not synchronized with your source code, usually the IDE should detect that, but it some cases it doesn't, the solution is to delete all binaries, recompile and try again.
A bug in the debugger or the debugger extension (used to debug in the specific environment your are in, i.e. unity/monodevelop).
If you are unable to resolve it, I would add logging to your code and use it to really understand what happens.
I saw similar behavior on MonoDevelop with WinForms applications, solved with reinstalling debugger.
Have you tried that or using Visual Studio to verify that the problem is in the code?
Do you have optimizations turned on? If so, does disabling them make stepping any less erratic?
Enabling optimizations is one thing I can think of that no one else has mentioned yet that could potentially cause what you are seeing.
Can you try removing you breakpoints, setting a new one, and stepping through the code?
The reason I ask is there are ways that you can set values using breakpoints. A very similar thing happened to me and was convinced that there was a compiler bug. After stepping through the CLR and number of other things with no answer, we stumbled across a breakpoint that was set earlier for testing, and never removed.
That kind of behavior usually happens to me when I'm debugging a multithreaded part of an application.
What happens is that while you debug several threads at once, the debugger in visual studio keeps switching between them without notifying you by default.
Now since threads are not executing the same lines at the same time, you got unexpected "jumps".
I believe it is widely used in game developpement, so in your case you got two choices:
1) Make only one thread run while you make your debugging.
2) Make unit tests <= That's the "best practice".
You can start by having a look at NUnit
The first issue most likely has something to do with the sequence points in the JITed code. These are the points where the debugger can stop. They're computed by the runtime based on the IL and debug symbols generated by the compiler, therefore this is most likely a runtime or compiler bug. I don't know what version of the Mono runtime and compiler is being used by Unity, but it's quite that this has been fixed in a newer version. If you can reproduce this using a "normal" console app using the latest official MonoDevelop and Mono 2.10.x, please file a bug at http://bugzilla.xamarin.com with a test case. If not, please ask Unity to upgrade their version of Mono.
The second issue looks like an issue in MonoDevelop's expression resolver that's used to resolve the symbol under the mouse. This may have been fixed in a newer version of MonoDevelop - likewise, please try to repro with the official MonoDevelop 2.8.4, and file a bug if it's still an issue.

Categories

Resources