Create OpenXML Table With C# - openxml

I'm having issues making an actual table in my excel file. The file is created and all the data is there, but when I open the file the table definition doesn't exist. I'm using this method to try and turn the data range into a table.
private static Table CreateTable(string tableRange, IEnumerable<string> headers)
{
var table = new Table {
Id = 1,
Name = "Table 1",
DisplayName = "Table 1",
Reference = tableRange,
TotalsRowShown = false,
HeaderRowFormatId = 0
};
table.AddNamespaceDeclaration("x", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
UInt32Value i = 1;
var columns = new TableColumns();
foreach (var header in headers) {
columns.Append(new TableColumn {
Id = i++,
Name = header
});
}
var style = new TableStyleInfo {
Name = "TableStyleMedium2",
ShowFirstColumn = false,
ShowLastColumn = false,
ShowRowStripes = true,
ShowColumnStripes = false
};
table.Append(new AutoFilter { Reference = tableRange });
table.Append(columns);
table.Append(style);
return table;
}
The tableRange variable is a simple excel range string, like "A1:D27". I'm trying to add it to the worksheet like so:
var tableDefinitionPart = worksheetPart.AddNewPart<TableDefinitionPart>();
tableDefinitionPart.Table = CreateTable(tableRange, headers);
I'm not getting any errors when I open the file.
If I open the file with the XML Productivity tool and click on the "x:table (Table)" part within the worksheet I see this:
<x:table xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" id="1" name="Table 1" displayName="Table 1" ref="A1:Z2" totalsRowShown="0" headerRowDxfId="0">
<x:autoFilter ref="A1:Z2" />
<x:tableColumns>
<x:tableColumn id="1" name="Lab Name" />
....
<x:tableColumn id="26" name="Description" />
</x:tableColumns>
<x:tableStyleInfo name="TableStyleMedium2" showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0" />
</x:table>
So it seems like I'm putting something properly into the file. It's just not an actual "table" as far as Excel is concerned.

Related

Adding Values to Custom Attribute using App Script

I have a requirement of adding Value to Custom attribute in G Suite for bulk users, I have added address and other field using App script but don't know how to add values to a custom attribute named "Enhanced Desktop Security" as shown in the image below.
Value to be added is using App Script is: "un:Windows"
Request your help with the Script.
I have been working on this and came to know that 1st you have to identify the schemas of the custom attribute here : https://developers.google.com/admin-sdk/directory/v1/reference/users/list Once you do that you can use the below script. Please make sure that you change the schema in the below script.
Mention "User Email ID", "Value", "Updation Status" in Cloumn A,B,C, respectively in sheet.
function updateCustomE() {
var ss = SpreadsheetApp.openById(""); // Mention ID of the spreadsheet here.
var sheet = ss.getSheetByName(""); // Mention Name of the sheet here.
var values = sheet.getDataRange().getValues();
var fileArray = [["Updation Status"]]
for(i=1; i <values.length; i++)
{
var userKey = values[i][0]
var customValue = values [i][1]
try{
var status = "Value not updated"
var status = AdminDirectory.Users.update({
"customSchemas": {
"Enhanced_desktop_security" : {
"Local_Windows_accounts" : [
{
"type": "custom",
"value": customValue
}
]
}
}
}, userKey);
if (status != "Value not updated"){
status = "Value updated Successfully"
}
}
catch (e) {
Logger.log(e.message)
var status = e.message
}
fileArray.push([status])
}
var range = sheet.getRange(1, 3, fileArray.length, 1).setValues(fileArray)
}

Corrupt records from OpenXML Spreadsheet creation

I'm trying to generate a simple XLSX file using OpenXML but I'm getting an error when I open my file and the only info in the repairedRecord part of the log file is this:
Repaired Records: Cell information from /xl/worksheets/sheet1.xml part
The strange thing is that all the cells I'm trying to write do have the value I expect them to have. I'm just trying to write a single header row right now, where the headers is just an IEnumerable<string>:
using (var doc = SpreadsheetDocument.Create(filename, SpreadsheetDocumentType.Workbook)) {
var workbookPart = doc.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
var sheets = workbookPart.Workbook.AppendChild(new Sheets());
var sheet = new Sheet {
Id = workbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = "Sheet 1"
};
sheets.Append(sheet);
workbookPart.Workbook.Save();
var sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());
var row = new Row { RowIndex = 1 };
var column = 1;
foreach (var header in headers)
row.AppendChild(new Cell {
CellReference = GetColumnLetter(column++) + "1",
DataType = CellValues.SharedString,
CellValue = new CellValue(header)
});
sheetData.Append(row);
workbookPart.Workbook.Save();
}
If you're inserting a string value, you should be using CellValues.InlineString
foreach (var header in headers)
row.AppendChild(new Cell (new InlineString(new Text(header))) {
CellReference = GetColumnLetter(column++) + "1",
DataType = CellValues.InlineString
});

How can I delete a row from a Table in SAPUI5 Application when I used Model as XMLModel?

I have created SAPUI5 application, in that I have loaded data from external .xml file into a table, it was fine. Now, I am trying to delete a specific row from that table.
For this purpose, I use this code:
var oModel = new sap.ui.model.xml.XMLModel();
oModel.loadData("Deployments.xml", "", false);
sap.ui.getCore().setModel(oModel);
oTable.bindRows("/service"); // here "service" is the root element of xml file
var oTable = new sap.ui.commons.Button({
text: "Delete Service",
press: function() {
var idx = oTable.getSelectedIndex();
if (idx !== -1) {
var m = oTable.getModel();
var data = m.getData();
var removed = data.splice(idx, 1); // error showing at this line
m.setData(data);
sap.m.MessageToast.show(JSON.stringify(removed[0]) + 'is removed');
} else {
sap.m.MessageToast.show('Please select a row');
}
}
});
But, I am getting error at the line: var removed = data.splice(idx, 1);. However, the same code is good for when model is JSON. How can I delete a specific row from a table when model XMLModel?
It is a lot easier an more reliable to use a Bindings BindingPath to manipulate data belonging to a particular binding. Here is your adapted sample for a XMLModel:
press: function() {
var iIdx = oTable.getSelectedIndex();
var sPath = oTable.getContextByIndex(iIdx).getPath();
var oObj = oTable.getModel().getObject(sPath);
oObj.remove();
oTable.getModel().refresh();
}
This way you save the hazzle of dealing with the XML structure and furthermore this will scale with any change in the binding path you might introduce in the future.
BR
Chris
var data = m.getData();
data is not an Array. It is a XML document.
To remove an entry from the document:
var root = data.childNodes[0];
var aEntry = root.getElementsByTagName("entry");
root.removeChild(aEntry[idx]);

Export MS Word Document pages to Images

I want to export MS word(docx/doc) document pages to Image(jpeg/png).
I am doing same for presentation(pptx/ppt) using office interop export api for each slide, but didn't found corresponding API for word.
Need suggestion for API/alternate approach for achieving this.
Based on this similar question: "Saving a word document as an image" you could do something like this:
const string basePath = #"C:\Users\SomeUser\SomePath\";
var docPath = Path.Combine(basePath, "documentA.docx");
var app = new Application()
{
Visible = true
};
var doc = app.Documents.Open(docPath);
foreach (Window window in doc.Windows)
{
foreach (Pane pane in window.Panes)
{
for (var i = 1; i <= pane.Pages.Count; i++)
{
var page = pane.Pages[i];
var bits = page.EnhMetaFileBits;
var target = Path.Combine(basePath, string.Format("page-no-{0}", i));
using (var ms = new MemoryStream(bits))
{
var image = Image.FromStream(ms);
var pngTarget = Path.ChangeExtension(target, "png");
image.Save(pngTarget, ImageFormat.Png);
}
}
}
}
app.Quit();
Basically, I'm using the Page.EhmMetaFileBits property which, according to the documentation:
Returns a Object that represents a picture representation of how a
page of text appears.
... and based on that, I create an image and save it to the disk.

Add Hyperlink to Cell in Excel 2007 Using Open XML SDK 2.0

I can't seem to find any documentation or code samples on how to add a hyperlink to a cell in Excel 2007 using the Open XML SDK 2.0. I am using the following code, but is there a step I am missing?
WorksheetPart workSheetPart = ExcelUtilities.GetWorkSheetPart(mWorkBookPart, "Program");
workSheetPart.AddHyperlinkRelationship(new Uri("http://www.google.com", UriKind.Absolute), true);
workSheetPart.Worksheet.Save();
mWorkBookPart.Workbook.Save();
Then when I try and open the Excel document it says the file is corrupted because the Relationship Id for the hyperlink cannot be found. How do you setup or create that Relationship Id?
Another possibility, (which I used), is to use the HYPERLINK formula for Excel. I needed to create individual hyperlinks in each cell, yet the cells had to display different text, (I had to display tracking numbers in the cells yet have a hyperlink for each tracking number to the carrier's site and had to handle multiple carriers).
Once I instantiated an individual cell, the formula was applied in this manner to each cell (there are undoubtedly numerous way):
// ...
Cell cell1 = new Cell(){ CellReference = "A1", StyleIndex = (UInt32Value)1U, DataType = CellValues.InlineString };
CellValue cellValue1 = new CellValue();
CellFormula cellFormula1 = new CellFormula() { Space = SpaceProcessingModeValues.Preserve };
cellFormula1.Text = #"HYPERLINK(""http://www.theclash.com"", ""Radio Clash"")";
cellValue1.Text = "Radio Clash";
cell1.Append(cellFormula1);
cell1.Append(cellValue1);
// append cell, etc.
In this way, I was able to create individual hyperlinks and text for each cell. By the way, the links will appear with the default font color unless you reference a style with blue font.
Hope this helps.
I was able to add a hyperlink to a cell using System.IO.Packaging code:
private void HyperlinkCreate(PackagePart part, XmlNamespaceManager nsm, XmlNode _cellElement, string CellAddress)
{
Uri _hyperlink = new Uri("http://www.yahoo.com");
XmlNode linkParent = _cellElement.OwnerDocument.SelectSingleNode("//d:hyperlinks", nsm);
if (linkParent == null)
{
// create the hyperlinks node
linkParent = _cellElement.OwnerDocument.CreateElement("hyperlinks", #"http://schemas.openxmlformats.org/spreadsheetml/2006/main");
XmlNode prevNode = _cellElement.OwnerDocument.SelectSingleNode("//d:conditionalFormatting", nsm);
if (prevNode == null)
{
prevNode = _cellElement.OwnerDocument.SelectSingleNode("//d:mergeCells", nsm);
if (prevNode == null)
{
prevNode = _cellElement.OwnerDocument.SelectSingleNode("//d:sheetData", nsm);
}
}
_cellElement.OwnerDocument.DocumentElement.InsertAfter(linkParent, prevNode);
}
string searchString = string.Format("./d:hyperlink[#ref = '{0}']", CellAddress);
XmlElement linkNode = (XmlElement)linkParent.SelectSingleNode(searchString, nsm);
XmlAttribute attr;
if (linkNode == null)
{
linkNode = _cellElement.OwnerDocument.CreateElement("hyperlink", #"http://schemas.openxmlformats.org/spreadsheetml/2006/main");
// now add cell address attribute
linkNode.SetAttribute("ref", CellAddress);
linkParent.AppendChild(linkNode);
}
attr = (XmlAttribute)linkNode.Attributes.GetNamedItem("id", #"http://schemas.openxmlformats.org/officeDocument/2006/relationships");
if (attr == null)
{
attr = _cellElement.OwnerDocument.CreateAttribute("r", "id", #"http://schemas.openxmlformats.org/officeDocument/2006/relationships");
linkNode.Attributes.Append(attr);
}
PackageRelationship relationship = null;
string relID = attr.Value;
if (relID == "")
relationship = part.CreateRelationship(_hyperlink, TargetMode.External, #"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink");
else
{
relationship = part.GetRelationship(relID);
if (relationship.TargetUri != _hyperlink)
relationship = part.CreateRelationship(_hyperlink, TargetMode.External, #"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink");
}
attr.Value = relationship.Id;
}
I then translated this code using the Open XML SDK 2.0 and it doesn't work. It seems the AddHyperlinkRelationship method doesn't actually add the relationship to the .rels file. I'm not sure why, but it sure seems like a bug to me.
private void HyperlinkCreate(PackagePart part, XmlNamespaceManager nsm, XmlNode _cellElement, string CellAddress)
{
WorksheetPart workSheetPart = ExcelUtilities.GetWorkSheetPart(mWorkBookPart, "Program");
Uri hyperlinkUri = new Uri("http://www.yahoo.com", UriKind.Absolute);
Hyperlinks hyperlinks = workSheetPart.Worksheet.Descendants<Hyperlinks>().FirstOrDefault();
// Check to see if the <x:hyperlinks> element exists; if not figure out
// where to insert it depending on which elements are present in the Worksheet
if (hyperlinks == null)
{
// Create the hyperlinks node
hyperlinks = new Hyperlinks();
OpenXmlCompositeElement prevElement = workSheetPart.Worksheet.Descendants<ConditionalFormatting>().FirstOrDefault();
if (prevElement == null)
{
prevElement = workSheetPart.Worksheet.Descendants<MergeCells>().FirstOrDefault();
if (prevElement == null)
{
// No FirstOrDefault needed since a Worksheet requires SheetData or the excel doc will be corrupt
prevElement = workSheetPart.Worksheet.Descendants<SheetData>().First();
}
}
workSheetPart.Worksheet.InsertAfter(hyperlinks, prevElement);
}
Hyperlink hyperlink = hyperlinks.Descendants<Hyperlink>().Where(r => r.Reference.Equals(CellAddress)).FirstOrDefault();
if (hyperlink == null)
{
hyperlink = new Hyperlink() { Reference = CellAddress, Id = string.Empty };
}
HyperlinkRelationship hyperlinkRelationship = null;
string relId = hyperlink.Id;
if (relId.Equals(string.Empty))
{
hyperlinkRelationship = workSheetPart.AddHyperlinkRelationship(hyperlinkUri, true);
}
else
{
hyperlinkRelationship = workSheetPart.GetReferenceRelationship(relId) as HyperlinkRelationship;
if (!hyperlinkRelationship.Uri.Equals(hyperlinkUri))
{
hyperlinkRelationship = workSheetPart.AddHyperlinkRelationship(hyperlinkUri, true);
}
}
hyperlink.Id = hyperlinkRelationship.Id;
hyperlinks.AppendChild<Hyperlink>(hyperlink);
workSheetPart.Worksheet.Save();
}
You should be adding it to an object that accepts hyperlinks, such as a cell, instead of the worksheet. Something like this should work for you:
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml;
namespace GeneratedCode
{
public class GeneratedClass
{
// Creates an Worksheet instance and adds its children.
public Worksheet GenerateWorksheet()
{
Worksheet worksheet1 = new Worksheet(){ MCAttributes = new MarkupCompatibilityAttributes(){ Ignorable = "x14ac" } };
worksheet1.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
worksheet1.AddNamespaceDeclaration("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
worksheet1.AddNamespaceDeclaration("x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
SheetDimension sheetDimension1 = new SheetDimension(){ Reference = "A1" };
SheetViews sheetViews1 = new SheetViews();
SheetView sheetView1 = new SheetView(){ TabSelected = true, WorkbookViewId = (UInt32Value)0U };
sheetViews1.Append(sheetView1);
SheetFormatProperties sheetFormatProperties1 = new SheetFormatProperties(){ DefaultRowHeight = 14.4D, DyDescent = 0.3D };
SheetData sheetData1 = new SheetData();
Row row1 = new Row(){ RowIndex = (UInt32Value)1U, Spans = new ListValue<StringValue>() { InnerText = "1:1" }, DyDescent = 0.3D };
Cell cell1 = new Cell(){ CellReference = "A1", StyleIndex = (UInt32Value)1U, DataType = CellValues.SharedString };
CellValue cellValue1 = new CellValue();
cellValue1.Text = "0";
cell1.Append(cellValue1);
row1.Append(cell1);
sheetData1.Append(row1);
Hyperlinks hyperlinks1 = new Hyperlinks();
Hyperlink hyperlink1 = new Hyperlink(){ Reference = "A1", Id = "rId1" };
hyperlinks1.Append(hyperlink1);
PageMargins pageMargins1 = new PageMargins(){ Left = 0.7D, Right = 0.7D, Top = 0.75D, Bottom = 0.75D, Header = 0.3D, Footer = 0.3D };
worksheet1.Append(sheetDimension1);
worksheet1.Append(sheetViews1);
worksheet1.Append(sheetFormatProperties1);
worksheet1.Append(sheetData1);
worksheet1.Append(hyperlinks1);
worksheet1.Append(pageMargins1);
return worksheet1;
}
}
}
Easiest way is to use the HyperLink formular, but the links aren't blue by default, this is why the styleIndex is set.
private Cell BuildHyperlinkCell(string url) =>
new Cell
{
DataType = new EnumValue<CellValues>(CellValues.String),
CellFormula = new CellFormula($"HyperLink(\"{url}\")"),
StyleIndex = 4u
};
Adding the styling to the workbook:
http://www.dispatchertimer.com/tutorial/how-to-create-an-excel-file-in-net-using-openxml-part-3-add-stylesheet-to-the-spreadsheet/