diff --git a/src/EPPlus/Constants/ExtLstUris.cs b/src/EPPlus/Constants/ExtLstUris.cs index fd78aeda61..d000ca8ef1 100644 --- a/src/EPPlus/Constants/ExtLstUris.cs +++ b/src/EPPlus/Constants/ExtLstUris.cs @@ -56,8 +56,16 @@ internal class ExtLstUris internal const string ConditionalFormattingUri = "{78C0D931-6437-407d-A8EE-F0AAD7539E65}"; internal const string ExtChildUri = "{B025F937-C7B1-47D3-B67F-A62EFF666E3E}"; - //Feature property bag refrence used for checkboxes is styling. + //Feature property bag refrence used for checkboxes is styling. (xfComplementXf) + /// + /// NOT FOR DXF + /// internal const string FeaturePropertyBag = "{C7286773-470A-42A8-94C5-96B5CB345126}"; + //dxfComplementExt + /// + /// FOR DXF + /// + internal const string FeaturePropertyBagDxf = "{0417FA29-78FA-4A13-93AC-8FF0FAFDF519}"; internal const string Connection2010Uri = "{DE250136-89BD-433C-8126-D09CA5730AF9}"; } diff --git a/src/EPPlus/Style/Dxf/DxfStyleHandler.cs b/src/EPPlus/Style/Dxf/DxfStyleHandler.cs index e6539e3093..a6c2ee7ad9 100644 --- a/src/EPPlus/Style/Dxf/DxfStyleHandler.cs +++ b/src/EPPlus/Style/Dxf/DxfStyleHandler.cs @@ -136,6 +136,15 @@ private static void UpdateDxfXmlTables(ExcelStyles styles, XmlNode dxfsNode, Exc foreach (var column in tbl.Columns) { column.HeaderRowDxfId = AddDxfNode(styles.Dxfs, dxfsNode, column.HeaderRowStyle); + + //if (column.DataDxfId.HasValue && column.DataStyle.DxfId == column.DataDxfId) + //{ + // //This is a no-op. The col already has the correct DataDxfId + //} + //else + //{ + // column.DataDxfId = AddDxfNode(styles.Dxfs, dxfsNode, column.DataStyle); + //} column.DataDxfId = AddDxfNode(styles.Dxfs, dxfsNode, column.DataStyle); column.TotalsRowDxfId = AddDxfNode(styles.Dxfs, dxfsNode, column.TotalsRowStyle); } diff --git a/src/EPPlus/Style/Dxf/ExcelDxfStyle.cs b/src/EPPlus/Style/Dxf/ExcelDxfStyle.cs index f74feaae82..64955bd68c 100644 --- a/src/EPPlus/Style/Dxf/ExcelDxfStyle.cs +++ b/src/EPPlus/Style/Dxf/ExcelDxfStyle.cs @@ -35,6 +35,7 @@ internal ExcelDxfStyle(XmlNamespaceManager nameSpaceManager, XmlNode topNode, Ex Font.SetValuesFromXml(_helper); Alignment.SetValuesFromXml(_helper); Protection.SetValuesFromXml(_helper); + Checkbox = _helper.ExistsNode($"d:extLst/d:ext[@uri='{ExtLstUris.FeaturePropertyBagDxf}']/xfpb:DXFComplement"); } } /// @@ -122,7 +123,7 @@ internal override void CreateNodes(XmlHelper helper, string path) var cmplNode = (XmlElement)helper.CreateNode("d:extLst/d:ext/xfpb:DXFComplement"); var extNode = (XmlElement)cmplNode.ParentNode; extNode.SetAttribute("xmlns:xfpb", Schemas.schemaFeaturePropertyBag); - extNode.SetAttribute("uri", ExtLstUris.FeaturePropertyBag); + extNode.SetAttribute("uri", ExtLstUris.FeaturePropertyBagDxf); cmplNode.SetAttribute("i", "0"); _styles._hasDxfCheckbox = true; } diff --git a/src/EPPlus/XmlHelper.cs b/src/EPPlus/XmlHelper.cs index 62b753a7b7..74584a47e1 100644 --- a/src/EPPlus/XmlHelper.cs +++ b/src/EPPlus/XmlHelper.cs @@ -24,6 +24,7 @@ Date Author Change using OfficeOpenXml.Packaging.Ionic.Zip; using OfficeOpenXml.Utils.TypeConversion; using OfficeOpenXml.Utils.EnumUtils; +using System.Xml.XPath; namespace OfficeOpenXml { @@ -595,6 +596,38 @@ internal XmlNode GetNode(string path) { return TopNode.SelectSingleNode(path, NameSpaceManager); } + + /// + /// If Get Node doesn't work. + /// Simplified way of applying the default node prefix to empty args. + /// + /// + /// + internal XmlNode GetDefaultNode(string path) + { + var retNode = GetNode(path); + + if (retNode == null) + { + var defaultPrefix = NameSpaceManager.LookupPrefix(NameSpaceManager.DefaultNamespace); + + var splitArgs = path.Split('/'); + + for (int i = 0; i < splitArgs.Length; i++) + { + if (splitArgs[i].Contains(":") == false) + { + //No prefix add default prefix + splitArgs[i] = splitArgs[i].Insert(0, defaultPrefix + ":"); + } + } + var alteredExp = string.Join("/", splitArgs.ToArray()); + retNode = GetNode(alteredExp); + } + + return retNode; + } + internal XmlNodeList GetNodes(string path) { return TopNode.SelectNodes(path, NameSpaceManager); diff --git a/src/EPPlusTest/VBA/VBATests.cs b/src/EPPlusTest/VBA/VBATests.cs index 423cfcb2dd..659d711f41 100644 --- a/src/EPPlusTest/VBA/VBATests.cs +++ b/src/EPPlusTest/VBA/VBATests.cs @@ -1,5 +1,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using OfficeOpenXml; +using OfficeOpenXml.Constants; +using OfficeOpenXml.Drawing; using OfficeOpenXml.Utils.VBA; using OfficeOpenXml.VBA; using OfficeOpenXml.VBA.ContentHash; @@ -12,6 +14,8 @@ using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; +using System.Xml; +using System.Xml.XPath; namespace EPPlusTest.VBA { @@ -300,5 +304,91 @@ public void VbaModuleNameShouldAllowSpace() var module = package.Workbook.VbaProject.Modules.AddModule("My BubbleChartModule"); module.Code = sb.ToString(); } + + + [TestMethod] + public void ReadAndSaveTemplateDxfIdsCheckbox() + { + using (var package = OpenTemplatePackage("i2273.xlsx")) + { + var ws = package.Workbook.Worksheets[0]; + SaveAndCleanup(package); + } + + using (var package = OpenPackage("i2273.xlsx")) + { + var ws = package.Workbook.Worksheets[0]; + + var tbl = ws.Tables[0]; + var cols = tbl.Columns; + + //Verify style bools + Assert.IsTrue(cols[0].DataStyle.Checkbox); + Assert.IsTrue(cols[1].DataStyle.Checkbox); + + var topNode = cols[0].DataStyle._helper.TopNode; + cols[0].DataStyle._helper.GetDefaultNode("extLst/ext"); + + //ws.Workbook.Styles + var extNode = (XmlElement)cols[0].DataStyle._helper.GetDefaultNode($"extLst/ext"); + var extNodeCol2 = (XmlElement)cols[0].DataStyle._helper.GetDefaultNode($"extLst/ext"); + + //Verify dxf property bag + Assert.IsTrue(extNode.GetAttribute("uri") == ExtLstUris.FeaturePropertyBagDxf); + Assert.IsTrue(extNodeCol2.GetAttribute("uri") == ExtLstUris.FeaturePropertyBagDxf); + + SaveAndCleanup(package); + } + } + + [TestMethod] + public void EnsureEpplusReadsXlsmDxfIdsForTablesCorrectly() + { + var fileName = "MyVBACheckboxes"; + var fileEnding = ".xlsm"; + + using (var package = OpenPackage(fileName + fileEnding, true)) + { + var ws = package.Workbook.Worksheets.Add("TableCheckboxes"); + package.Workbook.CreateVBAProject(); + + var tbl = ws.Tables.Add(ws.Cells["B2:C3"], "Table1"); + tbl.ShowHeader = true; + tbl.DataStyle.Checkbox = true; + tbl.Columns[0].DataStyle.Checkbox = true; + tbl.Columns[1].DataStyle.Checkbox = true; + + ws.Cells["B3:C3"].Value = false; + + SaveAndCleanup(package); + } + + using (var package = OpenPackage(fileName + fileEnding)) + { + var ws = package.Workbook.Worksheets[0]; + + var tbl = ws.Tables[0]; + var cols = tbl.Columns; + + //Verify style bools + Assert.IsTrue(tbl.DataStyle.Checkbox); + Assert.IsTrue(cols[0].DataStyle.Checkbox); + Assert.IsTrue(cols[1].DataStyle.Checkbox); + + var topNode = cols[0].DataStyle._helper.TopNode; + cols[0].DataStyle._helper.GetDefaultNode("extLst/ext"); + + //ws.Workbook.Styles + var extNode = (XmlElement)cols[0].DataStyle._helper.GetDefaultNode($"extLst/ext"); + var extNodeCol2 = (XmlElement)cols[0].DataStyle._helper.GetDefaultNode($"extLst/ext"); + + //Verify dxf property bag + Assert.IsTrue(extNode.GetAttribute("uri") == ExtLstUris.FeaturePropertyBagDxf); + Assert.IsTrue(extNodeCol2.GetAttribute("uri") == ExtLstUris.FeaturePropertyBagDxf); + + var outFile = GetOutputFile("", fileName + "_Resaved" + fileEnding); + package.SaveAs(outFile); + } + } } }