Excel xlXYScatter has lines when generated by C# - c#

I'm using an app written in WPF C# to generate an Excel Worksheet and plot out some data.
xlXYScatterLines, xlXYScatterLinesNoMarkers, xlXYScatterSmooth, xlXYScatterSmoothNomarkers all worked out fine.
Except for xlXYScatter which always produces connects the data point with lines (= xlXYScatterLines), while it is supposed to display only scattered dots. Below is my code.
Excel.ChartObjects xlCharts = (Excel.ChartObjects)oSheet.ChartObjects(Type.Missing);
Excel.ChartObject myChart = (Excel.ChartObject)xlCharts.Add(350,20,500,350);
Excel.Chart chartPage = myChart.Chart;
chartPage.ChartType = Excel.XlChartType.xlXYScatter;
is this a bug?
[SOLUTION - not answer]
After two days of playing around, I accidentally found if I set the source data before defining chart type. The problem would not occur and xlXYScatter will show as xlXYScatter, not xlXYScatterLines.
chartPage.SetSourceData(Range, Missing.Value);
chartPage.ChartType = Excel.XlChartType.xlXYScatter;
I do not understand why and how this gets around the problem because it a intuitive to define the source after you define the chart, and in the opposite doesn't make much sense.
So I consider this as a solution, but not an answer. Hope someone can still answer the question.

I haven't done this in C#, but in VBA I had some similar grief. I ended up having to create the chart as xlXYScatterLinesNoMarkers. Then after the chart was created, I changed the type to xlXYScatter. Ugly, but it seemed to work for me in VBA.

Related

Filter Range by specific Color Index/RGB using Worksheet.Range.Autofilter(Field,Criteria,Operator)

I am doing some automated excel manipulation using C#. I have been having a hard time figuring out how to autofilter based on a specific color.
There is very little documentation about this type of manipulation, however I have found some VB.net and VBA code for it. I cannot seem to convert the code to C# as "RGB" is not usable as it is in VB.net and VBA (See VB.net code below).
Since there has been no answers to this questions, I want to specify the code that needs to be looked at. In Autofilter(Field,Criteria,Operator), I need to know the C# Microsoft.Office.Interop.Excel criteria that would let me choose a color to filter.
Here is what my code looks like:
Excel.Worksheet xs1:
Excel.Range xRange1;
Excel.Range xRange2;
Excel.Range lastrow;
Excel.Range lastcol;
lastrow = xs1.Rows.End[Excel.XlDirection.xlDown];
lastcol = xs1.Columns.End[Excel.XlDirection.xlToRight];
xRange1 = xs1.Cells[2, 14];
xRange2 = xs1.Cells[lastrow.Row, 14];
Below selects the entire sheet and adds an autofilter(), setting it to filter for color. This works fine, but how do I pick the color I want it to filter for?
xs1.Range["A1", xs1.Cells[lastrow.Row, lastcol.Column]].
AutoFilter(14,Excel.XlColorIndex.xlColorIndexAutomatic,
Excel.XlAutoFilterOperator.xlFilterCellColor);
Here is an example of what the autofilter code would look like in VB.net. It looks very similar to this in an excel macro as well.
xs1.Range("A1", xs1.Cells(lastrow.Row, lastcol.Column)).
AutoFilter(Field:=14,Criteria1:=RGB(0,202,255),
Operator:=Excel.XlAutoFilterOperator.xlFilterCellColors)
So this is how you pick the color index for any poor souls that need to figure it out themselves. I could not find this anywhere on the internet.
xs1.Range["A1", xs1.Cells[lastrow.Row, lastcol.Column]].
AutoFilter(14, xlBook.Colors[33], Excel.XlAutoFilterOperator.xlFilterCellColor);
The important part is the "xlBook.Colors[33]". xlBook being the Workbook. 33 being the color index.
I don't have any reputation points, so I must submit an answer instead of a comment. Anyway, thank you, thank you, thank you. I have spent weeks looking for this answer and happened to search the right key words to find this post. I signed up just to upvote the answer!
My scenario is not exactly like yours, but similar enough that you led me to the solution. So, I will share what worked for me. I am trying to filter by color index using PowerShell. However, PowerShell does not allow the RGB values, as in the VB.net example above. Now, for my contribution to the answer. If you are doing this in PowerShell then it will need to look like this:
$xlFilterCellColor = 8
$xl = New-Object -comobject excel.application
$xl.Visible = $true
$xl.DisplayAlerts = $False
$wb = $xl.Workbooks.Open("\\path\to\file.xlsx")
$ws = $wb.worksheets.items(1)
$xlCellTypeLastCell = 11
$used = $ws.usedRange
$lastCell = $used.SpecialCells($xlCellTypeLastCell)
$range = $ws.range(A1:$lastCell)
$range.select | out-null
$range.autofilter(1,$wb.colors(6),$xlFilterCellColor)
The operator decimal values are listed here. In the code above, I am filtering yellow colored cells. Cell index colors and values can be found here.

Range.PastSpecial(...) is failing

I am using Interop.Excel for doing this task.
I am trying to copy a range of cells from one workbook's sheet and paste it into a separate workbook's sheet, but I want to keep the formatting from the source sheet and paste it into the destination sheet. I found the PasteSpecial, and tried to use that, but when I try it, I get an unhelpful exception message : "PastSpecial methos of Range class failed", which has an HResult of -2146827284. Could not find anything via google, so here I am to hopefully get some help...
I use the code below to try this. I also did try using Excel.XlPasteType.xlPasteAll as the initial parameter to the PastSpecial method, and that did actually Paste the data into the destination sheet, and so I thought great, this works, but when I looked closer, I could see, very fiently, what looked like extra gridlines, and when I clicked on the pasted data, it was a whole object which could be moved around, much like an image pasted in that can be moved. This of course is not what I wanted. The idea is that I need to preserve the formatting and the border styles and the colors used.
Many thanks for reading - apologies if my formatting in the post has messed up.
Excel.Range rng6 = sht6.Cells.get_Range("A1", "O55");
Excel.Range rng1 = sht.get_Range("A" + rowStart6.ToString(), "O" + rowEnd6.ToString());
rng6.Copy(mis);
/** Fails here at PasteSpecial**/
rng1.PasteSpecial(Excel.XlPasteType.xlPasteFormats, Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);

Auto column width in EPPlus

How to make columns to be auto width when texts in columns are long?
I use this code
Worksheet.Column(colIndex).AutoFitColumn() 'on all columns'
Worksheet.cells.AutoFitColumns()
Worksheet.Column(colIndex).BestFit = True 'on all columns'
None of these methods are working
Are there any ways to make it work?
Note: Some of my texts use Unicode.
Use AutoFitColumns, but you have to specify the cells, i assume the entire worksheet:
VB.NET
Worksheet.Cells(Worksheet.Dimension.Address).AutoFitColumns()
C#
Worksheet.Cells[Worksheet.Dimension.Address].AutoFitColumns();
Please note you need to call this method after filling the worksheet.
I have used this code with the version 3.1.3.0 of EPPlus and it is working:
worksheet.Column(1).AutoFit();
where a worksheet is the variable referencing the worksheet I have created in my code (not a class with a static method!).
Obviously you have to call this method after you have filled the columns.
Just wanted to point out you can fit cells with out specifying the range, just make sure to call this after you've formatted all columns etc:
worksheet.Cells.AutoFitColumns()
I know this is an old question, but I use the code below and it seems to directly address what you have tried to do.
using (var xls = new ExcelPackage())
{
var ws = xls.Workbook.Worksheets.Add("Some Name");
//**Add Column Names to worksheet!**
//**Add data to worksheet!**
const double minWidth = 0.00;
const double maxWidth = 50.00;
ws.Cells.AutoFitColumns(minWidth, maxWidth);
return pkg.GetAsByteArray();
}
I know is a little bit late but I've had the same problem today. If you have a worksheet.DefaultColWidthdefined, it won't work. I've removed that line and added Worksheet.cells.AutoFitColumns(); and it works now.
It's working just fine for me.
Try:
ExcelWorksheet wsSheet1 = ExcelPkg.Workbook.Worksheets.Add("Sheet1");
wsSheet1.Cells[wsSheet1.Dimension.Address].AutoFitColumns();
ExcelPkg.SaveAs();
The .NET Core as a successor of .NET doesn't support anymore the function autofit cells with EPPplus library.
worksheet.Cells.AutoFitColumns();
or
worksheet.Column(1).AutoFit();
causes exception:
"System.Drawing is not supported on this platform."
The System.Drawing assembly is dependent on GDI and Windows specific libraries which have to be replaced by another solution. The solution for this issue is to me unknown.
Had to use worksheet.Column(1).AutoFit(0); AutoFit() wasn't doing the trick.
You will need to calculate the width. There is no autosizing function in the library that will work as you intend.
Autofitcolumn will not work with wrapped text and cells with formulas.
Look at http://epplus.codeplex.com/discussions/218294?ProjectName=epplus for examples of how you can solve the problem.
I use this and is working well.
Dim objExcel As New ExcelPackage
Dim Sheet As ExcelWorksheet = objExcel.Workbook.Worksheets.Add("SheetName")
Sheet.Cells("B1:BN").AutoFitColumns()

excel xml window width property

This answer is strangely vacant from the internet, or my google-fu is getting rusty.
I'm making an excel file from C# via xml... When it loads up the worksheet width is pitifully small. Using <ss:WindowWidth>13395</ss:WindowWidth>
as prescribed by the internet does... nothing. (edit: tried this in excelworkbook and worksheetoptions, if that gives any idea to the problem) Tried with and without the ss: additions. Also, I cannot seem to find exactly why everyone uses values with this in and around the tens of thousands.
I'm thoroughly confused. If someone links a LMGTFY that answers this I'll eat my hat, because I damn well don't see it.
Silly excel. No one likes you.
Just for you L.
Figured windowWidth would give the jist of it.
I've seen some people add an ExcelWorkbook element to the 'Workbook' element. The ExcelWorkbook element has WindowWidth and WindowHeight elements.
Here is an example that lists (all?) of the child elements for the ExcelWorkbook element.
<Workbook>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>6795</WindowHeight>
<WindowWidth>8460</WindowWidth>
<WindowTopX>120</WindowTopX>
<WindowTopY>15</WindowTopY>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
...
</Workbook>
EDIT
The WindowWidth element is an unsigned int that is specified in twips. Twips is defined as a twentieth of a point.
Twips Link
http://en.wikipedia.org/wiki/Twip
You can maximize the workbook programmatically via the COM interface. In VBA you would do something like this:
ActiveWindow.WindowState = xlMaximized
Maybe that helps.

Does anyone have .Net Excel IO component benchmarks?

I'm needing to access Excel workbooks from .Net. I know all about the different ways of doing it (I've written them up in a blog post), and I know that using a native .Net component is going to be the fastest. But the question is, which of the components wins? Has anybody benchmarked them? I've been using Syncfusion XlsIO, but that's very slow for some key operations (like deleting rows in a workbook containing thousands of Named ranges).
I haven't done any proper benchmarks, but I tried out several other components,and found that SpreadsheetGear was considerably faster than XlsIO which I was using before. I've written up some of my findings in this post
Can't help you with your original question, but are you aware that you can access Excel files using an OleDbConnection, and therefore treat it as a database? You can then read worksheets into a DataTable, perform all the changes you need to the data in your application, and then save it all back to the file using an OleDbConnection.
Yes but I'm not going to publish them both out of a courtesy to Syncfusion (they ask you not to publish benchmarks), because I'm not an experienced tester so my tests are probably somewhat flawed but mostly because what you actually benchmark makes a huge difference to who wins and by how much.
I took one of their "performance" examples and added the same routine in EPPlus to compare them. XLSIO was around 15% faster with just straightforward inserts, depending on the row/column ratio (I tried a few), memory usage seemed very similar. When I added a routine that, after all the rows were added, deleted every 10th row and then inserted a new row 2 rows up from that - XLSIO was significantly slower in that circumstance.
A generic benchmark is pretty-much useless to you. You need to try them against each other in the specific scenarios you use.
I have been using EPPlus for a few years and the performance has been fine, I don't recall shouting at it.
More worthy of your consideration is the functionality, support (Syncfusion have been good, in my experience), Documentation, access to the source code if that is important, and - importantly - how much sense the API makes to you, the syntax can be quite different. eg. Named Styles
XLSIO
headerStyle.BeginUpdate();
workbook.SetPaletteColor(8, System.Drawing.Color.FromArgb(255, 174, 33));
headerStyle.Color = System.Drawing.Color.FromArgb(255, 174, 33);
headerStyle.Font.Bold = true;
headerStyle.Borders[ExcelBordersIndex.EdgeLeft] .LineStyle = ExcelLineStyle.Thin;
headerStyle.Borders[ExcelBordersIndex.EdgeRight] .LineStyle = ExcelLineStyle.Thin;
headerStyle.Borders[ExcelBordersIndex.EdgeTop] .LineStyle = ExcelLineStyle.Thin;
headerStyle.Borders[ExcelBordersIndex.EdgeBottom].LineStyle = ExcelLineStyle.Thin;
headerStyle.EndUpdate();
EPPlus
ExcelNamedStyleXml headerStyle = xlPackage.Workbook.Styles.CreateNamedStyle("HeaderStyle");
headerStyle.Style.Fill.PatternType = ExcelFillStyle.Solid; // <== needed or BackgroundColor throws an exception
headerStyle.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.FromArgb(255, 174, 33));
headerStyle.Style.Font.Bold = true;
headerStyle.Style.Border.Left.Style = ExcelBorderStyle.Thin;
headerStyle.Style.Border.Right.Style = ExcelBorderStyle.Thin;
headerStyle.Style.Border.Top.Style = ExcelBorderStyle.Thin;
headerStyle.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;

Categories

Resources