What is the difference between CellValues.InlineString and CellValues.String in OpenXML? - c#

I am trying to write some code to generate an Excel spreadsheet and I am not sure what the difference between CellValues.InlineString and CellValues.String to insert text on the cells.
Shall I use this:
private void UpdateCellTextValue(Cell cell,string cellValue)
{
InlineString inlineString = new InlineString();
Text cellValueText = new Text { Text = cellValue };
inlineString.AppendChild(cellValueText);
cell.DataType = CellValues.InlineString;
cell.AppendChild(inlineString);
}
this
private void UpdateCellTextValue(Cell cell, string cellValue)
{
cell.CellValue = new CellValue(cellValue);
cell.DataType = new EnumValue<CellValues>(CellValues.String);
}
or just this (InsertSharedStringItem returns the Id of the newly inserted shared string item)
private void SetCellSharedTextValue(Cell cell,string cellValue)
{
int stringId = InsertSharedStringItem(cellValue);
cell.CellValue = new CellValue(stringId.ToString());
cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
}

According to the documentation at 18.18.11 ST_CellType:
str (String) Cell containing a formula
string.
You will only want to use the CellValues.String when you are inserting a formula in the cell. Here is how the XML should look:
<x:c r="C6" s="1" vm="15" t="str">
<x:f>CUBEVALUE("xlextdat9 Adventure Works",C$5,$A6)</x:f>
<x:v>2838512.355</x:v>
</x:c>
CellValues.InlineString should only be used if you don't want to store the string in the SharedStringTable. Then anything you mark as an inlineString will be treated as rich text. Although note that when you use CellValues.InlineString that your text must be surounded by a text element and <is> tag:
<x:c r="B2" t="inlineStr">
<is><t>test string</t></is>
</c>

Related

Set Multiple styles in a single excel cell using OfficeOpenXml in C#

I cannot find a way to style a single excel cell in different styles.
For example I need to make only some part of the string bold and leave the rest unbold in one cell.
I can only access Cells not characters in OpenXml.
Usually what I do to style the cell is,
ExcelPackage package = new ExcelPackage();
ExcelWorksheet ws = package.Workbook.Worksheets.Add("SheetName");
ws.Cells[1, 1].Style.Font.Bold = true;
I can't find a way to access characters in a cell. I saw some other excel plugins do the same but Is there any way OpenXml can do this? Any suggestions will be great. Thanks
The answer here works well.
You have to add the cell content as separate ExcelRichText objects.
Example:
ExcelRichText rt1 = ws.Cells[1, 1].RichText.Add("AB");
rt1.Bold = true; // bold just the "AB"
ExcelRichText rt2 = ws.Cells[1, 1].RichText.Add("CD");
Output will be: "ABCD"
Note: You will need to reference the namespace OfficeOpenXml.Style
This is how you can add partial styles in an excel sheet using OpenXML.
//Partial Cell Styling
uint currentRow = 2;
Row newRow = new Row() { RowIndex = currentRow };
//create a new inline string cell
Cell cell = new Cell() { CellReference = "J" + currentRow.ToString() };
cell.DataType = CellValues.InlineString;
//create a run for the bold text
Run run1 = new Run();
run1.Append(new Text("By: "));
//create a second run for the non-bod text
Run run2 = new Run();
run2.Append(new Text(Environment.NewLine + " SAHIL VIG") { Space = SpaceProcessingModeValues.Preserve });
//create runproperties and append a "Bold" to them
RunProperties run2Properties = new RunProperties();
run2Properties.Append(new Bold());
//set the first runs RunProperties to the RunProperties containing the bold
run2.RunProperties = run2Properties;
//create a new inline string and append both runs
InlineString inlineString = new InlineString();
inlineString.Append(run1);
inlineString.Append(run2);
//append the inlineString to the cell.
cell.Append(inlineString);
//append the cell to the row
newRow.Append(cell);
sheetData.Append(newRow);

How can I export a C# DataGridView to PDF using iTextSharp while **maintaining the custom currency formatting**?

I'm trying to export a DataGridView with custom currency formatting to PDF using iTextSharp, the formatting shows up perfectly on the DataGrid when running the program but doesn't appear on the PDF once I save it.
Here is the DataGridView code (showing the currency formatting):
DataTable t = new DataTable();
if (t != null)
{
a.Fill(t);
//Custom currency formatting
var format = (NumberFormatInfo)NumberFormatInfo.CurrentInfo.Clone();
format.CurrencySymbol = "R";
dgvMiscEntries.AutoGenerateColumns = false;
dgvMiscEntries.ColumnCount = 2;
//Assign column headers manually
dgvMiscEntries.Columns[0].Name = "Description";
dgvMiscEntries.Columns[0].HeaderText = "Description";
dgvMiscEntries.Columns[0].DataPropertyName = "Description";
dgvMiscEntries.Columns[1].Name = "Rate";
dgvMiscEntries.Columns[1].HeaderText = "Rate";
dgvMiscEntries.Columns[1].DataPropertyName = "Rate";
dgvMiscEntries.Columns[1].DefaultCellStyle.FormatProvider = format;
dgvMiscEntries.Columns[1].DefaultCellStyle.Format = "c";
// Render data onto grid
dgvMiscEntries.DataSource = t;
}
And here is the iTextSharp code:
//Creating iTextSharp Misc Entries Table from the DataTable data
PdfPTable miscTable = new PdfPTable(dgvMiscEntries.ColumnCount);
miscTable.DefaultCell.Padding = 3;
float[] miscWidthPosit = new float[] { 1000f, 200f };
miscTable.WidthPercentage = 80;
miscTable.SetWidths(miscWidthPosit);
miscTable.HorizontalAlignment = Element.ALIGN_CENTER;
miscTable.DefaultCell.BorderWidth = 1;
miscTable.SpacingBefore = 10;
miscTable.DefaultCell.HorizontalAlignment = Element.ALIGN_LEFT;
foreach (DataGridViewRow row in dgvMiscEntries.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
if (cell.Value != null)
{
miscTable.AddCell(cell.Value.ToString());
}
}
}
I have searched for similar questions here and on other sites but I haven't found any addressing this particular problem.
Thats because the Value property takes the actual bound value which is used to provide the formatted text.
So instead of
miscTable.AddCell(cell.Value.ToString());
use FormattedValue
miscTable.AddCell(cell.FormattedValue.ToString());

open xml, set cellvalue html string

Technologies: C#, openxml
I am trying to create xlsx file using opennxml document. Data table contains one column with rich text in html string. example "hi" or hi
How to append/set value to cellValue.Text. Please suggest any other approach to achieve this.
Cell cell = new Cell() { CellReference = ExcelHelper.ColumnCaption.Instance.Get((Convert.ToInt32((UInt32)rowIndex) - 2), cIndex), DataType = CellValues.InlineString };
cell.DataType = new EnumValue<CellValues>(CellValues.String);
CellValue cellValue = new CellValue();
cellValue.Text = data.Rows[rIndex][cIndex].ToString();//<b>hi</b>
cell.Append(cellValue);

openxml 2.5, how to insert a string into a cell?

I have been trying for a couple of days now to insert a string into an openxml spreadsheet. Everything else (so far) works, everything but that.
This is the code i'm currently running (note, this is purely for testing purposes and is pretty basic):
using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Create(file + "test.zip", SpreadsheetDocumentType.Workbook))
{
spreadSheet.AddWorkbookPart();
spreadSheet.WorkbookPart.Workbook = new Workbook();
spreadSheet.WorkbookPart.AddNewPart<SharedStringTablePart>();
spreadSheet.WorkbookPart.SharedStringTablePart.SharedStringTable = new SharedStringTable() {Count=1, UniqueCount=1};
spreadSheet.WorkbookPart.SharedStringTablePart.SharedStringTable.AppendChild(new SharedStringItem(new Text("test")));
spreadSheet.WorkbookPart.SharedStringTablePart.SharedStringTable.Save();
preadSheet.WorkbookPart.AddNewPart<WorksheetPart>();
spreadSheet.WorkbookPart.WorksheetParts.First().Worksheet = new Worksheet();
spreadSheet.WorkbookPart.WorksheetParts.First().Worksheet.AppendChild(new SheetData());
spreadSheet.WorkbookPart.WorksheetParts.First().Worksheet.First().AppendChild(new Row());
Row r2 = new Row() { RowIndex = 5 };
spreadSheet.WorkbookPart.WorksheetParts.First().Worksheet.First().AppendChild(r2);
r2.AppendChild(new Cell() { CellReference = "A5", CellValue = new CellValue("0"), DataType = new EnumValue<CellValues>(CellValues.SharedString) });
spreadSheet.WorkbookPart.WorksheetParts.First().Worksheet.Save();
spreadSheet.WorkbookPart.Workbook.GetFirstChild<Sheets>().AppendChild(new Sheet()
{
Id = spreadSheet.WorkbookPart.GetIdOfPart(spreadSheet.WorkbookPart.WorksheetParts.First()),
SheetId = 1,
Name = "test"
});
spreadSheet.WorkbookPart.Workbook.Save();
}
Everything seems to work, the file saves where i want it to and, generally, looks the way i expect it to. The "only" issue is that, when i add the string to the cell, excel will give me an error saying that the file is corrupt and continues to delete said cell.
Am i doing something wrong?
Try this, in your method..
if (spreadSheet.WorkbookPart.GetPartsOfType<SharedStringTablePart>().Count() > 0)
{
shareStringPart = spreadSheet.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();
}
else
{
shareStringPart = spreadSheet.WorkbookPart.AddNewPart<SharedStringTablePart>();
}
index = InsertSharedStringItem(cell_value, shareStringPart);
cell.CellValue = new CellValue(index.ToString());
cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
InsertSharedString Method:
private static int InsertSharedStringItem(string text, SharedStringTablePart shareStringPart)
{
// If the part does not contain a SharedStringTable, create one.
if (shareStringPart.SharedStringTable == null)
{
shareStringPart.SharedStringTable = new SharedStringTable();
}
int i = 0;
// Iterate through all the items in the SharedStringTable. If the text already exists, return its index.
foreach (SharedStringItem item in shareStringPart.SharedStringTable.Elements<SharedStringItem>())
{
if (item.InnerText == text)
{
return i;
}
i++;
}
// The text does not exist in the part. Create the SharedStringItem and return its index.
shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(text)));
shareStringPart.SharedStringTable.Save();
return i;
}
I think you should create a spreadsheet (using Excel), add the text into the cell and then open this spreadsheet in "OpenXML 2.5 Productivity Tool". There is a "Reflect code" button in the productivity tool that would help you replicate in code what needs to be done. That's the easiest way, I've found to solve such bugs.

How to get value shown in cell from .xlsx using open XML C#

Im new to C# and open XML, so please be patient with my ingnorance.
I have this problem:
I need to get cell value from .xlsx file. I can do that using XlGetCellValue method.
But When one cell (for example A2 from sheet1) gets it value from another cell (B2 sheet2)
XlGetCellValue("", "Sheet1", "A2")
returns Sheet2!B2Joe.
Or when the cell contains computation (like =C2+D2), XlGetCellValue(...) returns C2+D2120
Is there any easy way to get just value "Joe" and "120?
Here the link to MSDN on how to get the value of a cell using the Open XML SDK 2.5. There is a code sample provided.
How to: Retrieve the values of cells in a spreadsheet document (Open XML SDK)
Working with openxmnl could be a pain in the ass if you haven't yet downloaded OpenXMLSDKToolV25.msi (Productivity tool).
basically it's a reflection tool. you can open an excel document and the tool create all code you need to build the same from scratch.
CellValue it's only for value. using formula you have to deal with cell formula.
Eg. I created an excel file in A1 = 1256 in B1 = 2 in C1 "=A1*B1"
Opening the file with OpenXMLSDKTool i got:
public Row GenerateRow()
{
Row row1 = new Row(){ RowIndex = (UInt32Value)1U, Spans = new ListValue<StringValue>() { InnerText = "1:3" } };
Cell cell1 = new Cell(){ CellReference = "A1" };
CellValue cellValue1 = new CellValue();
cellValue1.Text = "1256";
cell1.Append(cellValue1);
Cell cell2 = new Cell(){ CellReference = "B1" };
CellValue cellValue2 = new CellValue();
cellValue2.Text = "2";
cell2.Append(cellValue2);
Cell cell3 = new Cell(){ CellReference = "C1" };
CellFormula cellFormula1 = new CellFormula();
cellFormula1.Text = "A1*B1";
CellValue cellValue3 = new CellValue();
cellValue3.Text = "2512";
cell3.Append(cellFormula1);
cell3.Append(cellValue3);
row1.Append(cell1);
row1.Append(cell2);
row1.Append(cell3);
return row1;
}
from this you can notice that CellValue and CellFormula are both childs of Cell.
So, assuming you can retrieve your Row r you can have this:
Cell c = r.Elements<Cell>().ElementAt(2);
CellValue cv = c.CellValue;
CellFormula cf = c.CellFormula;

Categories