How do I write this Excel Interop syntax in EPPLUS syntax - c#

Someone suggested to me a method to improve my code by making it more manageable through the use of objects:
string[,] values = new string[15, 35]; //or objects
values[7, 7] = "2016";
values[7, 28] = drag24;
values[7, 33] = drag25;
values[10, 8] = digit1;
values[10, 11] = digit2;
// etc.
Range range = WS.Range[WS.Cells[1, 1], WS.Cells[15, 35]];
range.Value = values;
His suggestion, but since I moved from interop to EPPLUS, the following syntax no longer works.
Range range = WS.Range[WS.Cells[1, 1], WS.Cells[15, 35]];
What would a working form of this look like in EPPLUS Syntax?
Replacing it with this didnt work out right and replaced everything in the sheet:
ExcelRange range = WS.Cells["A1: AH106"]
Perhaps something like this?
= sheet.Cells["A1:,12:12,14:14"]

Not sure if this is exactly what you mean, but here's a simple example with a custom object, and arrays:
Test object:
class TestObject
{
public int Id { get; set; }
public string Name { get; set; }
}
Populating a sheet with the custom object, and arrays:
IEnumerable<TestObject> objectList = new List<TestObject>()
{
{ new TestObject() {Id = 0, Name = "zero" } },
{ new TestObject() {Id = 1, Name = "one" } }
};
var values = new List<object[]>()
{
new string[] { "one", "two" },
new string[] { "three", "four" }
};
using (var package = new ExcelPackage())
{
var sheet = package.Workbook.Worksheets.Add("Sheet1");
// note second parameter gives you headings
sheet.Cells["A1"].LoadFromCollection<TestObject>(objectList, true);
sheet.Cells["A4"].LoadFromArrays(values);
File.WriteAllBytes(OUTPUT, package.GetAsByteArray());
}

Related

CSV File with cells containing commas, Reading data into C# Program

I'm writing a program to read in CSV files and validate the data. The csv file is comma delimited.
The csv file contains a sales order that is retrieved online so we can't actually edit the CSV file itself. I need to read in the file and split it into the cells. However, the product description will contain further commas which is affecting how I access the data.
My code for pulling the values out is below.
private void csvParse()
{
List<string> products = new List<string>();
List<string> quantities = new List<string>();
List<string> price = new List<string>();
using (var reader = new StreamReader(txt_filePath.Text.ToString()))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
products.Add(values[0]);
quantities.Add(values[2]);
values[3] = values[3].Substring(4);
price.Add(values[3]);
}
}
if (validateData(products, quantities, price) != "")
{
MessageBox.Show(validateData(products, quantities, price));
}
}
Is there anyway to ignore the columns in a set cell or can the columns distinguished by another delimiter?
A snippet of a row in my csv file is below.
The raw CSV data is below:
TO12345,"E45 Dermatological Moisturising Lotion, 500 ml",765,GBP 1.75
You can use LinqToCSV from nuGet. ie:
void Main()
{
List<MyData> sample = new List<MyData> {
new MyData {Id=1, Name="Hammer", Description="Everything looks like a nail to a hammer, doesn't it?"},
new MyData {Id=2, Name="C#", Description="A computer language."},
new MyData {Id=3, Name="Go", Description="Yet another language, from Google, cross compiles natively."},
new MyData {Id=3, Name="BlahBlah"},
};
string fileName = #"c:\temp\MyCSV.csv";
File.WriteAllText(fileName,"Id,My Product Name,Ignore1,Ignore2,Description\n");
File.AppendAllLines(fileName, sample.Select(s => $#"{s.Id},""{s.Name}"",""ignore this"",""skip this too"",""{s.Description}"""));
CsvContext cc = new CsvContext();
CsvFileDescription inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = true,
IgnoreUnknownColumns=true
};
IEnumerable<MyData> fromCSV = cc.Read<MyData>(fileName, inputFileDescription);
foreach (var d in fromCSV)
{
Console.WriteLine($#"ID:{d.Id},Name:""{d.Name}"",Description:""{d.Description}""");
}
}
public class MyData
{
[CsvColumn(FieldIndex = 1, Name="Id", CanBeNull = false)]
public int Id { get; set; }
[CsvColumn(FieldIndex = 2, Name="My Product Name",CanBeNull = false, OutputFormat = "C")]
public string Name { get; set; }
[CsvColumn(FieldIndex = 5, Name="Description",CanBeNull = true, OutputFormat = "C")]
public string Description { get; set; }
}
It should work..:)
var csvSplit = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)", RegexOptions.Compiled);
string[] csvlines = File.ReadAllLines(txt_filePath.Text.ToString());
var query = csvlines.Select(csvline => new
{
data = csvSplit.Matches(csvline)
}).Select(t => t.data);
var row = query.Select(matchCollection =>
(from Match m in matchCollection select (m.Value.Contains(',')) ? m.Value.Replace(",", "") : m.Value)
.ToList()).ToList();
You can also use the Microsoft.VisualBasic.FileIO.TextFieldParser class. More detailed answer here: TextFieldParser

How to Use Virtual Mode for large data in DataGridView

I am posting to see if there is a way to improve some legacy code. The code will populate a DataGridView with x amount of rows. Initially, the code worked fine as the populating data was of a small quantity. However, there has been an extreme increase in data and I am finding that the performance in populating the DataGridView to be very slow.
Basically, I know there are several considerations (Virtual Mode, for instance). However, the approach that I want to take is using an array or List (and then convert it to an array) and add the range of the row by calling Rows.AddRange(array). However, I am having trouble implementing it.
As it stands, this is what code exists:
if (value !=0)
{
int row = 0;
dataGridView1.AddRow();
dataGridView1.Rows[row].Cells[0] = "Test";
dataGridView1.Rows[row].Cells[1] = 9;
dataGridView1.Rows[row].Cells[2] = "Test Two";
dataGridView1.Rows[row].Cells[3] = "Test Three";
row++;
}
if (valueTwo !=0)
{
dataGridView1.AddRow();
dataGridView1.Rows[row].Cells[0] = "Test";
dataGridView1.Rows[row].Cells[1] = 9;
dataGridView1.Rows[row].Cells[2] = "Test Two";
dataGridView1.Rows[row].Cells[3] = "Test Three";
row++;
}
So, this is not efficient at all, of course. I know .AddRow() is a taxing method in itself and individually adding rows, one-by-one is not great.
I have tried something like:
object[] data = {"Test", 9, "Test Two", "Test Three"};
List<DataGridViewRow> list = new List<DataGridViewRow>();
for (int i = 0; i < data.Length; i++)
{
DataGridViewRow row = new DataGridViewRow();
row.SetValues(data[i]);
list.Add(row);
}
dataGridViewRow1.Rows.AddRange(list.ToArray());
However, doing this gets me a NullPointerException on the SetValues line.
I understand that the best way of doing this is either make a DataTable or use Virtual Mode but I want to try out using this method of adding the range and passing in a container for the data, rather than adding a row.
I hope I am clear with my explanation. Let me know if I need to further explain.
EDIT: I think using Virtual Mode is the best way to go. I am not sure how to really do it, though. I checked MSN's tutorial but I was slightly confused by it. If I were to implement Virtual Mode for 100,000 rows, how would I go about doing it. Nothing really fancy, just displaying a total of 10,000 rows.
i can prefer DataTable is the correct approach,
but still if you want to add data to your gridView dynamically,
first you need to add columns then rows.
private void Form5_Load(object sender, EventArgs e)
{
var lstTemp = new List<test>();
for (int i = 0; i < 10; i++)
lstTemp.Add(new test() { Name = "Test", No = i, Desc = "Desc " + i, Desc1 = "Desc1 " + i });
dataGridView1.Columns.Add("Name", "Name");
dataGridView1.Columns.Add("No", "Number");
dataGridView1.Columns.Add("Desc", "Description1");
dataGridView1.Columns.Add("Desc1", "Description2");
foreach (var temp in lstTemp)
{
DataGridViewRow row = (DataGridViewRow) dataGridView1.Rows[0].Clone();
row.Cells[0].Value = temp.Name;
row.Cells[1].Value = temp.No;
row.Cells[2].Value = temp.Desc;
row.Cells[3].Value = temp.Desc1;
dataGridView1.Rows.Add(row);
}
}
public class test
{
public string Name { get; set; }
public int No { get; set; }
public string Desc { get; set; }
public string Desc1 { get; set; }
}
this might help you,
for your case you need to add columns before rows,
object[] data = { "Test", 9, "Test Two", "Test Three" };
dataGridView1.Columns.Add("Name", "Name");
dataGridView1.Columns.Add("No", "Number");
dataGridView1.Columns.Add("Desc", "Description1");
dataGridView1.Columns.Add("Desc1", "Description2");
for (int i = 0; i < 10; i++)
dataGridView1.Rows.Add(data);
Try to use a BindingList that you populate with your data, you can have a class to map the propreties or use a dynamic one. You have to frist create the cols so you can Bind de data: hereĀ“s one example:
DataGridViewCell cell = new DataGridViewTextBoxCell();
DataGridViewTextBoxColumn colFileName = new DataGridViewTextBoxColumn()
{
CellTemplate = cell,
Name = "Value1",
HeaderText = "Value 1",
DataPropertyName = "Col1"
};
DataGridViewCell cell2 = new DataGridViewTextBoxCell();
DataGridViewTextBoxColumn colFileName2 = new DataGridViewTextBoxColumn()
{
CellTemplate = cell2,
Name = "Value2",
HeaderText = "Value 2",
DataPropertyName = "Col2"
};
dataGridView1.Columns.Add(colFileName);
dataGridView1.Columns.Add(colFileName2);
List<DataPopulate> list = new List<DataPopulate>();
list.Add(new DataPopulate() { Col1 = "tes1", Col2 = "teste2"});
list.Add(new DataPopulate() { Col1 = "tes1", Col2 = "teste2" });
list.Add(new DataPopulate() { Col1 = "tes1", Col2 = "teste2" });
var dataPopulateList = new BindingList<DataPopulate>(list);
dataGridView1.DataSource = dataPopulateList;

epplus using LoadFromCollection with anonymous types

I have a IEnumerable<object> dataSource which contains a collection anonymous types. The actual structure of the anonymous type won't be known at design time, so I'm trying to find a generic solution that can handle any anonymous type.
How can I load them into epplus to create a spreadsheet? I have a worksheet called ws and I tried:
ws.Cells["A1"].LoadFromCollection(dataSource, true);
However when that runs it outputs all of the anonymous type's properties into a single cell:
{ Id = 10000, Title = This is a test }
I've tried passing in MemberInfo using:
var members = dataSource.First().GetType().GetMembers();
ws.Cells["A1"].LoadFromCollection(this._dataSource, true,
TableStyles.Medium1, BindingFlags.Public, members);
But that throws an exception:
Supplied properties in parameter Properties must be of the same type as T
Any suggestions on how I can create a spreadsheet using anonymous types in c#?
I have tested
using (var excel = new OfficeOpenXml.ExcelPackage())
{
var sheet = excel.Workbook.Worksheets.Add("Test");
sheet.Cells["A1"].LoadFromCollection(dataSource, true);
excel.SaveAs(new FileInfo(#"C:\Temp\Test.xlsx"));
}
with this sample data:
var dataSource = Enumerable.Range(1, 100).Select(i => new{ ID=i, Title="Title " + i });
It works fine. It creates two columns with the correct headers and 100 rows.
But you should use anonymous types only if you know the structure at compile time.
You could use a DataTable and LoadFromDataTable instead. Since i don't know how you create the anonymous type i show you just a small sample:
DataTable dataSource = new DataTable();
dataSource.Columns.Add("Id"); // default type is string
dataSource.Columns.Add("Title");
// add other columns
dataSource.Rows.Add("1", "Title1");
// add other rows
using (var excel = new OfficeOpenXml.ExcelPackage())
{
var sheet = excel.Workbook.Worksheets.Add("Test");
sheet.Cells["A1"].LoadFromDataTable(dataSource, true);
excel.SaveAs(new FileInfo(#"C:\Temp\Test.xlsx"));
}
You could group the anonymous types to make it easier for exporting with dataTables. The bug "Supplied properties in parameter Properties must be of the same type as T" is still there and a workaround is using DataTables.
// Imagine list is your main datasource
IEnumerable<object> list = Enumerable.Empty<object>(); // Data Source of <object>
// Added anon types at runtime added to the object list
var anonTypesOne = new object[]
{
new { GuidID = Guid.NewGuid(), StringProperty = "the string property" },
new { IntegerID = 1, IntegerProperty = 99 }
};
var anonTypesTwo = new object[]
{
new { StringID = "1", BooleanProperty = true, NumberProperty = 3, StringProperty = "Four" },
new { GuidID = Guid.NewGuid(), NumberThree = 3 },
new { GuidID = Guid.NewGuid(), NumberThree = 3 },
new { GuidID = Guid.NewGuid(), NumberThree = 3 }
};
list = list.Concat(anonTypesOne).Concat(anonTypesTwo);
// Grouping works on anon types so we can group the export into their own tables
var groupings = list.GroupBy(i => i.GetType());
using(var package = new ExcelPackage(new FileInfo("C:\\Temp\\Anon.xlsx")))
{
var ws = package.Workbook.Worksheets.Add("Anonymous Types");
// add each "anon type matched grouping"
foreach(var grouping in groupings)
{
var isNew = ws.Dimension == null; // the sheet is empty if Dimension is null.
var row = 0;
if(isNew)
{
row = 1; // start from the first row
}
else
{
// otherwise there are tables already, start from the bottom
row = ws.Dimension.End.Row;
}
// because of EPP inheritance bug of T, we can just use dataTable
DataTable dt = new DataTable(grouping.Key.Name);
var properties = grouping.Key.GetProperties(); // Get anon type Properties
foreach(var property in properties)
{
dt.Columns.Add(property.Name);
}
foreach(var item in grouping.ToList())
{
var dataRow = dt.NewRow();
foreach(var p in properties) // populate a single row
{
dataRow[p.Name] = p.GetValue(item); // item is anon object instance
}
dt.Rows.Add(dataRow);
}
if(isNew) // load into the top most left cell of the worksheet
ws.Cells[1, 1].LoadFromDataTable(dt, PrintHeaders: true);
else // load from the dimension of current items + 1 row for spacing
ws.Cells[ws.Dimension.End.Row + 1, 1].LoadFromDataTable(dt, PrintHeaders: true);
ws.InsertRow(ws.Dimension.End.Row + 2, 5); // Insert some padding between each group
}
package.Save();
}
I was, this thread is older, but I'm looking for the same problem.
With the following code (VB) I have success.
Carsten
Dim targetFile = New IO.FileInfo(sFN)
Dim dataSource = Enumerable.Range(0, 1).Select(Function(i) New With {.ID = 1000, .Titel = "This is a test "}).ToList
Using epp = New OfficeOpenXml.ExcelPackage(targetFile)
Dim ws = epp.Workbook.Worksheets.Add("lst_Anonymous")
ws.Cells(1, 1).LoadFromCollection(dataSource, True,
OfficeOpenXml.Table.TableStyles.Medium1,
Reflection.BindingFlags.Public,
dataSource.GetType.GetGenericArguments()(0).GetProperties)
epp.Save()
End Using

Invalid Argument in Method when pulling from repository

I am trying to learn how this Repository works by disecting it. I am really lost so was hoping the community would help me out a bit. Please keep in mind I am new to MVC so don't tear me apart to much. The error I am getting is because I have invalid arguments. I think it is from my 3rd argument but I am not quite sure how to fix it.
ResponentRepository.GetRespondents() is the problem Notice below.
In my controller I have:
List<int> projectIdsToInclude = new List<int>();
projectIdsToInclude.Add(4);
List<int> statusesToInclude = new List<int>();
statusesToInclude.Add(1);
List<string> fieldsToInclude = new List<string>();
fieldsToInclude.Add("firstName");
IEnumerable<int> pID = projectIdsToInclude;
IEnumerable<string> fields = fieldsToInclude;
var respondents = RespondentRepository.GetRespondents(UserSession, pID, statusesToInclude, fields);
In the Respository it has:
public List<Respondent> GetRespondents(UserSessionData sessionData, IEnumerable<int> projectIdsToInclude, IEnumerable<RespondentStatus> statusesToInclude, IEnumerable<string> fieldsToInclude)
{
var request = new RespondentRequest
{
Options = new RequestOptions
{
Include = fieldsToInclude,
//OrderBy = new List<OrderBy> { new OrderBy { Direction = OrderByDirection.Descending, Field = Create.Name<Respondent>(r => r.LastActionDate) } },
Filter = new LogicExpression
{
ExpressionA = new InExpression<int>
{
Field = Create.Name<Respondent>(r => r.ProjectId),
Values = projectIdsToInclude.ToList()
},
ExpressionB = new InExpression<RespondentStatus>
{
Field = Create.Name<Respondent>(r => r.RecruitingStatus),
Values = statusesToInclude.ToList()
},
Operator = SqlOperator.And
},
}
};
return Get(request, sessionData).Data;
}
My Invalid Argument I think is coming from the argument that is IEnumerable. So when I follow RespondentStatus I see this:
public enum RespondentStatus : int
{
[Description("Not Contacted")]
NotContacted = 0,
[Description("Pre-Screened")]
PreScreened = 1,
[Description("On Hold")]
Hold = 2,
[Description("Initial Refusal")]
InitialRefusal = 3,
[Description("Qualified Refusal")]
QualifiedRefusal = 4,
[Description("Remove From Panel")]
RemoveFromPanel = 5,
Terminated = 6,
Complete = 7,
//Probably should never reuse '8' as a status since retiring "Approved" status
Approved = 8,
// Phone contact statuses
[Description("No Answer")]
NoAnswer = 30,
Busy = 31,
[Description("Left Message")]
LeftMessage = 32,
[Description("Call Back Later")]
CallBackLater = 33,
[Description("Non-working Number")]
NonWorkingNumber = 34,
}
How do I fix my code in the controller to pull respondents from this repository? I just want to return some respondents. I think if I can do that I can further dissect from there. Can someone explain what I should do to make this work or what I am missing?
statusesToInclude should be IEnumerable<RespondentStatus> You are expecting IEnumerable<RespondentStatus> in you method, but calling it with List<int>.
Either change your method signature or your calling code so that the two statusesToInclude variables match up and have the same type.
For example:
List<RespondentStatus> statusesToInclude = new List<RespondentStatus>();
statusesToInclude.Add((RespondentStatus)1);

Excel found unreadable content in *.xlsx

I am working on generating an excel template from code. When I run the piece to create my WorkBook, I get no errors in code, however when I go to open the Excel document, I get an error indicating that the file is unreadable. I am able to click to open it anyway, and I get the following message
Removed Records: Worksheet properties from /xl/workbook.xml part (Workbook)
Any idea what might be wrong in my code please?
public void CreatePackage()
{
using (SpreadsheetDocument package = SpreadsheetDocument.Create(FilePath, SpreadsheetDocumentType.Workbook))
{
CreateParts(package);
}
}
private void CreateParts(SpreadsheetDocument document)
{
ExcelWorkBook excelworkbook = new ExcelWorkBook();
ExcelSheetHelper excelworksheet = new ExcelSheetHelper();
ExcelSharedStringsTable excelsharedtable = new ExcelSharedStringsTable();
ExcelWorkSheetPartBuilder excelworksheetbuilder = new ExcelWorkSheetPartBuilder();
ExtendedFilePropertiesPart extendedFilePropertiesPart1 = document.AddNewPart<ExtendedFilePropertiesPart>("rId3");
ExcelWorkSheetPartBuilder.GenerateExtendedFilePropertiesPart1Content(extendedFilePropertiesPart1);
WorkbookPart workbookPart1 = document.AddWorkbookPart();
excelworkbook.GenerateWorkbookPartContent(workbookPart1);
WorkbookStylesPart workbookStylesPart1 = workbookPart1.AddNewPart<WorkbookStylesPart>("rId5");
ExcelWorkBook.GenerateWorkbookStylesPart1Content(workbookStylesPart1);
SetPackageProperties(document);
}
public void GenerateWorkbookPartContent(WorkbookPart workbookPart1)
{
Workbook workbook = new Workbook();
workbook.AddNamespaceDeclaration("r", rNameSpace);
FileVersion fileVersion1 = GenerateFileVersion();
WorkbookProperties workbookProperties1 = GenerateWorkbookProperties();
BookViews bookViews1 = GenerateBookViews();
Sheets sheets1 = GenerateSheets();
DefinedNames definedNames1 = GenerateDefinedNames();
CalculationProperties calculationProperties1 = GenerateCalculationProperties();
CustomWorkbookViews customWorkbookViews1 = GenerateCustomWorkbookViews();
workbook.Append(fileVersion1);
workbook.Append(workbookProperties1);
workbook.Append(bookViews1);
workbook.Append(sheets1);
workbook.Append(definedNames1);
workbook.Append(calculationProperties1);
workbook.Append(customWorkbookViews1);
workbookPart1.Workbook = workbook;
}
// Creates an FileVersion instance and adds its children.
public FileVersion GenerateFileVersion()
{
FileVersion fileVersion1 = new FileVersion() { ApplicationName = "xl", LastEdited = "5", LowestEdited = "5", BuildVersion = "9303" };
return fileVersion1;
}
// Creates an WorkbookProperties instance and adds its children.
public WorkbookProperties GenerateWorkbookProperties()
{
WorkbookProperties workbookProperties1 = new WorkbookProperties() { HidePivotFieldList = true };
return workbookProperties1;
}
// Creates an BookViews instance and adds its children.
public BookViews GenerateBookViews()
{
BookViews bookViews1 = new BookViews();
WorkbookView workbookView1 = new WorkbookView() { XWindow = -75, YWindow = 270, WindowWidth = (UInt32Value)15435U, WindowHeight = (UInt32Value)6930U };
bookViews1.Append(workbookView1);
return bookViews1;
}
// Creates an Sheets instance and adds its children.
public Sheets GenerateSheets()
{
Sheets sheets1 = new Sheets();
Sheet sheet1 = new Sheet() { Name = String.Format("{0}", worksheetname), SheetId = (UInt32Value)8U, Id = "rId1" };
sheets1.Append(sheet1);
return sheets1;
}
// Creates an DefinedNames instance and adds its children.
public DefinedNames GenerateDefinedNames()
{
DefinedNames definedNames1 = new DefinedNames();
DefinedName definedName1 = new DefinedName() { Name = "_xlnm._FilterDatabase", LocalSheetId = (UInt32Value)0U, Hidden = true };
definedName1.Text = String.Format("\'{0}\'!$A$6:$EO$1269", worksheetname);
DefinedName definedName2 = new DefinedName() { Name = "Z_32BE30F1_B609_44A0_A38A_666CEFFB64E2_.wvu.Cols", LocalSheetId = (UInt32Value)0U, Hidden = true };
definedName2.Text = String.Format("\'{0}\'!#REF!", worksheetname);
DefinedName definedName3 = new DefinedName() { Name = "Z_32BE30F1_B609_44A0_A38A_666CEFFB64E2_.wvu.FilterData", LocalSheetId = (UInt32Value)0U, Hidden = true };
definedName3.Text = String.Format("\'{0}\'!#REF!", worksheetname);
DefinedName definedName4 = new DefinedName() { Name = "Z_5098B70B_692A_450A_8DAE_5172C296966E_.wvu.FilterData", LocalSheetId = (UInt32Value)0U, Hidden = true };
definedName4.Text = String.Format("\'{0}\'!#REF!", worksheetname);
DefinedName definedName5 = new DefinedName() { Name = "Z_7C00A233_927A_41FE_802C_48F5F9E9D5B6_.wvu.FilterData", LocalSheetId = (UInt32Value)0U, Hidden = true };
definedName5.Text = String.Format("\'{0}\'!#REF!",worksheetname);
DefinedName definedName6 = new DefinedName() { Name = "Z_AC112ED6_0017_40BF_884A_9B7959C37BF0_.wvu.FilterData", LocalSheetId = (UInt32Value)0U, Hidden = true };
definedName6.Text = String.Format("\'{0}\'!#REF!", worksheetname);
DefinedName definedName7 = new DefinedName() { Name = "Z_E444BF53_6DCE_4910_823C_F60AE88C96EE_.wvu.FilterData", LocalSheetId = (UInt32Value)0U, Hidden = true };
definedName7.Text = String.Format("\'{0}\'!#REF!",worksheetname);
definedNames1.Append(definedName1);
definedNames1.Append(definedName2);
definedNames1.Append(definedName3);
definedNames1.Append(definedName4);
definedNames1.Append(definedName5);
definedNames1.Append(definedName6);
definedNames1.Append(definedName7);
return definedNames1;
}
// Creates an CalculationProperties instance and adds its children.
public CalculationProperties GenerateCalculationProperties()
{
CalculationProperties calculationProperties1 = new CalculationProperties() { CalculationId = (UInt32Value)125725U };
return calculationProperties1;
}
// Creates an CustomWorkbookViews instance and adds its children.
public CustomWorkbookViews GenerateCustomWorkbookViews()
{
CustomWorkbookViews customWorkbookViews1 = new CustomWorkbookViews();
CustomWorkbookView customWorkbookView1 = new CustomWorkbookView() { Name = "A - Personal View", Guid = "{5098B70B-692A-450A-8DAE-5172C296966E}", MergeInterval = (UInt32Value)0U, PersonalView = true, Maximized = true, XWindow = 1, YWindow = 1, WindowWidth = (UInt32Value)1366U, WindowHeight = (UInt32Value)494U, ActiveSheetId = (UInt32Value)3U };
CustomWorkbookView customWorkbookView2 = new CustomWorkbookView() { Name = "B - Personal View", Guid = "{7C00A233-927A-41FE-802C-48F5F9E9D5B6}", MergeInterval = (UInt32Value)0U, PersonalView = true, Maximized = true, XWindow = 1, YWindow = 1, WindowWidth = (UInt32Value)1024U, WindowHeight = (UInt32Value)487U, ActiveSheetId = (UInt32Value)3U };
CustomWorkbookView customWorkbookView3 = new CustomWorkbookView() { Name = "C - Personal View", Guid = "{32BE30F1-B609-44A0-A38A-666CEFFB64E2}", MergeInterval = (UInt32Value)0U, PersonalView = true, Maximized = true, XWindow = 1, YWindow = 1, WindowWidth = (UInt32Value)1280U, WindowHeight = (UInt32Value)481U, ActiveSheetId = (UInt32Value)3U };
customWorkbookViews1.Append(customWorkbookView1);
customWorkbookViews1.Append(customWorkbookView2);
customWorkbookViews1.Append(customWorkbookView3);
return customWorkbookViews1;
}
public void ValidateDocument()
{
try
{
OpenXmlValidator validator = new OpenXmlValidator();
int count = 0;
IDictionary<String, String> ErrorLog = new Dictionary<String, String>();
using (StreamWriter f = new StreamWriter("Errolog.txt"))
{
foreach (ValidationErrorInfo error in validator.Validate(WordprocessingDocument.Open(FilePath, true)))
{
count++;
f.WriteLine("Error " + count);
f.WriteLine("Description: " + error.Description);
f.WriteLine("Path: " + error.Path.XPath);
f.WriteLine("Part: " + error.Part.Uri);
f.WriteLine("-------------------------------------------");
f.WriteLine("-------------------------------------------");
f.WriteLine("-------------------------------------------");
}
f.Flush();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
In my specific case, I was having this problem because of too long Worksheet names. This is what was happening to me:
On the first run of my program, I was trying to creating Worksheets with really big names.
Excel automatically cropped the big names to 31 characters. No exception was thrown. That is, I thought I was saving the original big name but I was actually saving the 31 characters long cropped string.
On the second run of my program, I was checking if this specific Worksheet existed already, but I thought it didn't exist because the existing one was cropped.
I was saving the Worksheet again. No exception thrown, but then, the new one was also cropped and now the XML contains 2 definitions of the same worksheet.
This causes Excel to attempt to repair the resulting Spreadsheet. Even though it works properly, I think it was simply throwing away the second one and using the first, which wasn't what I wanted.
I fixed the problem by cropping the 31 characters beforehand, before all the comparisons. Now it works perfectly
I know this question asked long ago, i thought my experience will solve someones problem. So am posting my answer here.
I had a similar problem. It occurs due the no. of characters in a sheet name exceeds the limit 31. Sheet name characters must be <= 31.
It won't throw any exception while creating, but gives error while opening in Microsoft Excel.
The Open XML SDK does not constrain you to producing a valid document. However, there is the OpenXmlValidator class which you can use to report any errors in the generated document. See this, which has a good example.
I had this error as well, because I was using 0 as my SheetId, something like:
var sheet1 = new Sheet() { Name = "Test", SheetId = (UInt32Value)0U, Id = "rId1" };
Excel starts counting from 1, not 0. This is not only true for row numbers, it applies to sheet numbers as well.
Yes, As Murugesan Said in the above comment, i fixed this error by renaming the file name of my excel document.
For example: In my case , the name of the document was 'My Sample Export Data Sheet'. I have renamed the file to 'MySampleExportDataSheet' and everything worked well later.
In my case the tab name consists single quote, i.e.: "my tab's".
I just omitted them:
title = title.replace(/'/g, "");
In our case, some of our worksheet names contained square brackets, e.g.:
Students [Primary]
Students [Secondary]
Replacing square brackets with round brackets fixed it:
Students (Primary)
Students (Secondary)
(For some reason, our customer didn't want these worksheets called Primary Students, Secondary Students, hence using brackets)
For us, the error message when opening the workbook in Excel was:
We found a problem with some content in 'workbook.xlsx'.
Do you want us to try and recover as much as we can?
If you trust the source of this workbook, click Yes.
Clicking Yes then allowed Excel to open the workbook, and it displayed the message
Repaired Records: Worksheet properties from /xl/workbook.xml part (Workbook)
Just in case someone finds this. It may also be because your sheet names are not unique. My issue was that, because of the char limit, 3 sheets wound up with the exact same name. When I repaired the file Excel renamed the duplicate sheets.
So if the above answers don't work, repair the file then look for a sheet named Recovered_Sheet1. That will tell you what sheet name has the issue (duplicate in my case).

Categories

Resources