GetParagraphs()
+ {
+ return paragraphs;
+ }
+ /**
+ * Appends a new {@link XWPFParagraph} to this footnote.
+ *
+ * @return The new {@link XWPFParagraph}
+ */
+ public XWPFParagraph CreateParagraph()
+ {
+ XWPFParagraph p = new XWPFParagraph(this.ctFtnEdn.AddNewP(), this);
+ paragraphs.Add(p);
+ bodyElements.Add(p);
+
+ // If the paragraph is the first paragraph in the footnote,
+ // ensure that it has a footnote reference run.
+ if (p.Equals(GetParagraphs()[0]))
+ {
+ EnsureFootnoteRef(p);
+ }
+ return p;
+ }
+
+ /**
+ * Ensure that the specified paragraph has a reference marker for this
+ * footnote by adding a footnote reference if one is not found.
+ * This method is for the first paragraph in the footnote, not
+ * paragraphs that will refer to the footnote. For references to
+ * the footnote, use {@link XWPFParagraph#addFootnoteReference(XWPFFootnote)}.
+ *
+ * The first run of the first paragraph in a footnote should
+ * contain a {@link CTFtnEdnRef} object.
+ *
+ * @param p The {@link XWPFParagraph} to ensure
+ */
+ public void EnsureFootnoteRef(XWPFParagraph p)
+ {
+
+ XWPFRun r = null;
+ if (p.Runs.Count > 0)
+ {
+ r = p.Runs[0];
+ }
+ if (r == null)
+ {
+ r = p.CreateRun();
+ }
+ CT_R ctr = r.GetCTR();
+ bool foundRef = false;
+ foreach (CT_FtnEdnRef reference in ctr.GetFootnoteReferenceList())
+ {
+ if (Id.ToString().Equals(reference.id))
+ {
+ foundRef = true;
+ break;
+ }
+ }
+ if (!foundRef)
+ {
+ ctr.AddNewRPr().AddNewRStyle().val="FootnoteReference";
+ ctr.AddNewFootnoteRef();
+ }
+ }
+
+ /**
+ * Appends a new {@link XWPFTable} to this footnote
+ *
+ * @return The new {@link XWPFTable}
+ */
+ public XWPFTable CreateTable()
+ {
+ XWPFTable table = new XWPFTable(ctFtnEdn.AddNewTbl(), this);
+ if (bodyElements.Count == 0)
+ {
+ XWPFParagraph p = CreateParagraph();
+ EnsureFootnoteRef(p);
+ }
+ bodyElements.Add(table);
+ tables.Add(table);
+ return table;
+ }
+
+ /**
+ * Appends a new {@link XWPFTable} to this footnote
+ * @param rows Number of rows to initialize the table with
+ * @param cols Number of columns to initialize the table with
+ * @return the new {@link XWPFTable} with the specified number of rows and columns
+ */
+ public XWPFTable CreateTable(int rows, int cols)
+ {
+ XWPFTable table = new XWPFTable(ctFtnEdn.AddNewTbl(), this, rows, cols);
+ bodyElements.Add(table);
+ tables.Add(table);
+ return table;
+ }
/**
*
* @param cursor
diff --git a/ooxml/XWPF/Usermodel/XWPFFootnotes.cs b/ooxml/XWPF/Usermodel/XWPFFootnotes.cs
index 01ed32009..4aba717ab 100644
--- a/ooxml/XWPF/Usermodel/XWPFFootnotes.cs
+++ b/ooxml/XWPF/Usermodel/XWPFFootnotes.cs
@@ -123,7 +123,7 @@ public List GetFootnotesList()
public XWPFFootnote GetFootnoteById(int id)
{
foreach(XWPFFootnote note in listFootnote) {
- if(note.GetCTFtnEdn().id == id.ToString())
+ if(note.GetCTFtnEdn().id == id)
return note;
}
return null;
@@ -167,7 +167,44 @@ public void SetXWPFDocument(XWPFDocument doc)
{
document = doc;
}
+ ///
+ /// Create a new footnote and add it to the document.
+ ///
+ ///
+ /// The new note will have one paragraph with the style "FootnoteText"
+ /// and one run containing the required footnote reference with the
+ /// style "FootnoteReference".
+ ///
+ /// New XWPFFootnote
+ public XWPFFootnote CreateFootnote()
+ {
+ CT_FtnEdn newNote = new CT_FtnEdn();
+ newNote.type = ST_FtnEdn.normal;
+
+ XWPFFootnote footnote = AddFootnote(newNote);
+ int id = ctFootnotes.SizeOfFootnoteArray;
+ footnote.GetCTFtnEdn().id = id;
+ return footnote;
+ }
+ ///
+ /// Remove the specified footnote if present.
+ ///
+ ///
+ ///
+ public bool RemoveFootnote(int pos)
+ {
+ if (ctFootnotes.SizeOfFootnoteArray >= pos - 1)
+ {
+ ctFootnotes.RemoveFootnote(pos);
+ listFootnote.RemoveAt(pos);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
/**
* @see NPOI.XWPF.UserModel.IBody#getPart()
*/
@@ -182,6 +219,8 @@ public XWPFDocument GetXWPFDocument()
return (XWPFDocument)GetParent();
}
}
+
+
}//end class
diff --git a/ooxml/XWPF/Usermodel/XWPFParagraph.cs b/ooxml/XWPF/Usermodel/XWPFParagraph.cs
index a3ee5349b..d5b393792 100644
--- a/ooxml/XWPF/Usermodel/XWPFParagraph.cs
+++ b/ooxml/XWPF/Usermodel/XWPFParagraph.cs
@@ -1647,6 +1647,19 @@ public XWPFHyperlinkRun CreateHyperlinkRun(string rId)
iRuns.Add(xwpfRun);
return xwpfRun;
}
+ ///
+ /// Add a new run with a reference to the specified footnote. The footnote reference run will have the style name "FootnoteReference".
+ ///
+ /// Footnote to which to add a reference.
+ public void AddFootnoteReference(XWPFFootnote footnote)
+ {
+ XWPFRun run = CreateRun();
+ CT_R ctRun = run.GetCTR();
+ var rstyle=ctRun.AddNewRPr().AddNewRStyle();
+ rstyle.val="FootnoteReference";
+ var footnoteRef = ctRun.AddNewFootnoteReference();
+ footnoteRef.id= footnote.Id.ToString();
+ }
}
}
\ No newline at end of file
diff --git a/ooxml/XWPF/Usermodel/XWPFRun.cs b/ooxml/XWPF/Usermodel/XWPFRun.cs
index 9cf6ee837..d91326240 100644
--- a/ooxml/XWPF/Usermodel/XWPFRun.cs
+++ b/ooxml/XWPF/Usermodel/XWPFRun.cs
@@ -279,7 +279,7 @@ public bool IsBold
{
get
{
- CT_RPr pr = run.rPr;
+ CT_RPr pr = GetRunProperties(false);
if (pr == null || !pr.IsSetB())
{
return false;
@@ -288,7 +288,7 @@ public bool IsBold
}
set
{
- CT_RPr pr = run.IsSetRPr() ? run.rPr : run.AddNewRPr();
+ CT_RPr pr = GetRunProperties(true);
CT_OnOff bold = pr.IsSetB() ? pr.b : pr.AddNewB();
bold.val = value;
}
@@ -302,8 +302,8 @@ public String GetColor()
String color = null;
if (run.IsSetRPr())
{
- CT_RPr pr = run.rPr;
- if (pr.IsSetColor())
+ CT_RPr pr = GetRunProperties(false);
+ if (pr!=null&&pr.IsSetColor())
{
NPOI.OpenXmlFormats.Wordprocessing.CT_Color clr = pr.color;
color = clr.val; //clr.xgetVal().getStringValue();
@@ -318,7 +318,7 @@ public String GetColor()
*/
public void SetColor(String rgbStr)
{
- CT_RPr pr = run.IsSetRPr() ? run.rPr : run.AddNewRPr();
+ CT_RPr pr = GetRunProperties(true);
NPOI.OpenXmlFormats.Wordprocessing.CT_Color color = pr.IsSetColor() ? pr.color : pr.AddNewColor();
color.val = (rgbStr);
}
@@ -386,14 +386,14 @@ public bool IsItalic
{
get
{
- CT_RPr pr = run.rPr;
+ CT_RPr pr = GetRunProperties(false);
if (pr == null || !pr.IsSetI())
return false;
return IsCTOnOff(pr.i);
}
set
{
- CT_RPr pr = run.IsSetRPr() ? run.rPr : run.AddNewRPr();
+ CT_RPr pr = GetRunProperties(true);
CT_OnOff italic = pr.IsSetI() ? pr.i : pr.AddNewI();
italic.val = value;
}
@@ -411,11 +411,36 @@ public UnderlinePatterns Underline
{
get
{
- CT_RPr pr = run.rPr;
- return (pr != null && pr.IsSetU() && pr.u.val != null) ?
- EnumConverter.ValueOf(pr.u.val) : UnderlinePatterns.None;
+ var value = UnderlinePatterns.None;
+ CT_Underline underline = GetCTUnderline(false);
+ if (underline != null)
+ {
+ ST_Underline baseValue = underline.val;
+ value = EnumConverter.ValueOf(baseValue);
+ }
+ return value;
+ }
+ set {
+ CT_Underline underline = GetCTUnderline(true);
+ underline.val = EnumConverter.ValueOf(value);
}
}
+ /**
+ * Get the CTUnderline for the run.
+ * @param create Create a new underline if necessary
+ * @return The underline, or null create is false and there is no underline.
+ */
+ private CT_Underline GetCTUnderline(bool create)
+ {
+ CT_RPr pr = GetRunProperties(true);
+ CT_Underline underline = pr.u;
+ if (create && underline == null)
+ {
+ underline = pr.AddNewU();
+ }
+ return underline;
+ }
+
internal void InsertText(CT_Text text, int textIndex)
{
run.GetTList().Insert(textIndex, text);
@@ -526,24 +551,6 @@ public string Text
return text.ToString();
}
}
- /**
- * Specifies that the contents of this run.should be displayed along with an
- * underline appearing directly below the character heigh
- * If this element is not present, the default value is to leave the
- * formatting applied at previous level in the style hierarchy. If this
- * element is never applied in the style hierarchy, then an underline shall
- * not be applied to the contents of this run.
- *
- * @param value -
- * underline type
- * @see UnderlinePatterns : all possible patterns that could be applied
- */
- public void SetUnderline(UnderlinePatterns value)
- {
- CT_RPr pr = run.IsSetRPr() ? run.rPr : run.AddNewRPr();
- CT_Underline underline = (pr.u == null) ? pr.AddNewU() : pr.u;
- underline.val = EnumConverter.ValueOf(value);
- }
/**
* Specifies that the contents of this run.shall be displayed with a single
@@ -1153,7 +1160,7 @@ XWPFPicture AddPicture(Stream pictureData, int pictureType, String filename, int
prstGeom.prst = (ST_ShapeType.rect);
prstGeom.AddNewAvLst();
- using (var ms = new MemoryStream())
+ using (var ms = RecyclableMemory.GetStream())
{
StreamWriter sw = new StreamWriter(ms);
pic.Write(sw, "pic:pic");
@@ -1269,7 +1276,29 @@ static void preserveSpaces(CT_Text xs)
xs.space = "preserve";
}
}
-
+ public String Lang
+ {
+ get
+ {
+ CT_RPr pr = GetRunProperties(false);
+ Object lang = pr == null || !pr.IsSetLang() ? null : pr.lang.val;
+ return (String)lang;
+ }
+ set {
+ CT_RPr pr = GetRunProperties(true);
+ CT_Language ctLang = pr.IsSetLang() ? pr.lang : pr.AddNewLang();
+ ctLang.val = value;
+ }
+ }
+ protected CT_RPr GetRunProperties(bool create)
+ {
+ CT_RPr pr = run.IsSetRPr() ? run.rPr : null;
+ if (create && pr == null)
+ {
+ pr = run.AddNewRPr();
+ }
+ return pr;
+ }
/**
* Returns the string version of the text, with tabs and
* carriage returns in place of their xml equivalents.
diff --git a/ooxml/XWPF/Usermodel/XWPFSDTContentCell.cs b/ooxml/XWPF/Usermodel/XWPFSDTContentCell.cs
index d54fd4980..1074720fd 100644
--- a/ooxml/XWPF/Usermodel/XWPFSDTContentCell.cs
+++ b/ooxml/XWPF/Usermodel/XWPFSDTContentCell.cs
@@ -167,7 +167,6 @@ private bool IsStartToken(object cursor, String string1)
//{
// return true;
//}
- return false;
}
diff --git a/ooxml/XWPF/Usermodel/XWPFStyles.cs b/ooxml/XWPF/Usermodel/XWPFStyles.cs
index 0a063bf24..1f8145b52 100644
--- a/ooxml/XWPF/Usermodel/XWPFStyles.cs
+++ b/ooxml/XWPF/Usermodel/XWPFStyles.cs
@@ -35,7 +35,7 @@ public class XWPFStyles : POIXMLDocumentPart
{
private CT_Styles ctStyles;
private List listStyle = new List();
-
+ public IReadOnlyList listOfStyles { get => listStyle; }
private XWPFLatentStyles latentStyles;
private XWPFDefaultRunStyle defaultRunStyle;
private XWPFDefaultParagraphStyle defaultParaStyle;
diff --git a/ooxml/XWPF/Usermodel/XWPFTable.cs b/ooxml/XWPF/Usermodel/XWPFTable.cs
index 7c9941cd7..5b64de3d0 100644
--- a/ooxml/XWPF/Usermodel/XWPFTable.cs
+++ b/ooxml/XWPF/Usermodel/XWPFTable.cs
@@ -654,6 +654,58 @@ public int CellMarginRight
}
}
+ public string TableCaption
+ {
+ get
+ {
+ CT_TblPr tblPr = GetTrPr();
+ if (tblPr.tblCaption != null)
+ return tblPr.tblCaption.val;
+ else
+ return string.Empty;
+ }
+ set
+ {
+ CT_TblPr tblPr = GetTrPr();
+ if (tblPr.tblCaption == null)
+ {
+ CT_String caption = new CT_String();
+ caption.val = value;
+ tblPr.tblCaption = caption;
+ }
+ else
+ {
+ tblPr.tblCaption.val = value;
+ }
+ }
+ }
+
+ public string TableDescription
+ {
+ get
+ {
+ CT_TblPr tblPr = GetTrPr();
+ if (tblPr.tblDescription != null)
+ return tblPr.tblDescription.val;
+ else
+ return string.Empty;
+ }
+ set
+ {
+ CT_TblPr tblPr = GetTrPr();
+ if (tblPr.tblDescription == null)
+ {
+ CT_String desc = new CT_String();
+ desc.val = value;
+ tblPr.tblDescription = desc;
+ }
+ else
+ {
+ tblPr.tblDescription.val = value;
+ }
+ }
+ }
+
public void SetCellMargins(int top, int left, int bottom, int right)
{
CT_TblPr tblPr = GetTrPr();
@@ -807,6 +859,7 @@ public XWPFTableRow GetRow(CT_Row row)
}
return null;
}
+
}// end class
}
\ No newline at end of file
diff --git a/ooxml/XWPF/Usermodel/XWPFTableRow.cs b/ooxml/XWPF/Usermodel/XWPFTableRow.cs
index d20e1c212..c909079e4 100644
--- a/ooxml/XWPF/Usermodel/XWPFTableRow.cs
+++ b/ooxml/XWPF/Usermodel/XWPFTableRow.cs
@@ -107,7 +107,12 @@ public XWPFTableCell AddNewTableCell()
tableCells.Add(tableCell);
return tableCell;
}
-
+ public XWPFTableRow CloneRow()
+ {
+ XWPFTableRow clonedRow= new XWPFTableRow(ctRow.Copy(), this.table);
+ table.AddRow(clonedRow);
+ return clonedRow;
+ }
/**
* This element specifies the height of the current table row within the
diff --git a/ooxml/packages.config b/ooxml/packages.config
index d460d74a6..7e45f57f7 100644
--- a/ooxml/packages.config
+++ b/ooxml/packages.config
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/openxml4Net/Exceptions/InvalidFormatException.cs b/openxml4Net/Exceptions/InvalidFormatException.cs
index 655b1ed91..bcee376ab 100644
--- a/openxml4Net/Exceptions/InvalidFormatException.cs
+++ b/openxml4Net/Exceptions/InvalidFormatException.cs
@@ -6,8 +6,6 @@ namespace NPOI.OpenXml4Net.Exceptions
{
public class InvalidFormatException:OpenXml4NetException
{
- private string p;
- private InvalidFormatException ex;
public InvalidFormatException(String message):base(message)
{
diff --git a/openxml4Net/Exceptions/OpenXML4NetException.cs b/openxml4Net/Exceptions/OpenXML4NetException.cs
index 8a7a2a4a2..ae8ba25cd 100644
--- a/openxml4Net/Exceptions/OpenXML4NetException.cs
+++ b/openxml4Net/Exceptions/OpenXML4NetException.cs
@@ -5,9 +5,6 @@ namespace NPOI.OpenXml4Net
{
public class OpenXml4NetException : Exception
{
- private Exceptions.InvalidFormatException ex;
-
-
public OpenXml4NetException(String msg)
: base(msg)
{
diff --git a/openxml4Net/NPOI.OpenXml4Net.csproj b/openxml4Net/NPOI.OpenXml4Net.csproj
index 3342421de..382ffe597 100644
--- a/openxml4Net/NPOI.OpenXml4Net.csproj
+++ b/openxml4Net/NPOI.OpenXml4Net.csproj
@@ -73,7 +73,7 @@
TRACE;HIDE_UNREACHABLE_CODE
..\solution\Lib\.net45\NPOI.OpenXml4Net.XML
true
- 1591
+ 1591;1587;1570
pdbonly
AnyCPU
7.3
diff --git a/openxml4Net/OPC/Internal/ContentType.cs b/openxml4Net/OPC/Internal/ContentType.cs
index 507b265d6..ad5971c24 100644
--- a/openxml4Net/OPC/Internal/ContentType.cs
+++ b/openxml4Net/OPC/Internal/ContentType.cs
@@ -45,7 +45,6 @@ public class ContentType:IComparable
/**
* Parameters
*/
- Hashtable p;
private Dictionary parameters;
/**
diff --git a/openxml4Net/OPC/PackagePart.cs b/openxml4Net/OPC/PackagePart.cs
index ea7e7375e..75b0463ba 100644
--- a/openxml4Net/OPC/PackagePart.cs
+++ b/openxml4Net/OPC/PackagePart.cs
@@ -112,7 +112,15 @@ public abstract class PackagePart : RelationshipSource, IComparable
{
}
-
+ ///
+ /// Check if the new part was already added before via PackagePart.addRelationship()
+ ///
+ /// to find the relationship for
+ /// The existing relationship, or null if there isn't yet one
+ public PackageRelationship FindExistingRelation(PackagePart packagePart)
+ {
+ return _relationships.FindExistingInternalRelation(packagePart);
+ }
/**
* Adds an external relationship to a part (except relationships part).
*
@@ -503,7 +511,7 @@ public PackagePart GetRelatedPart(PackageRelationship rel)
{
target = PackagingUriHelper.ParseUri(t.Substring(0, t.IndexOf('#')), UriKind.Absolute);
}
- catch (UriFormatException e)
+ catch (UriFormatException)
{
throw new InvalidFormatException("Invalid target URI: " + t);
}
diff --git a/openxml4Net/OPC/PackageRelationshipCollection.cs b/openxml4Net/OPC/PackageRelationshipCollection.cs
index 087f2e001..417e44ba6 100644
--- a/openxml4Net/OPC/PackageRelationshipCollection.cs
+++ b/openxml4Net/OPC/PackageRelationshipCollection.cs
@@ -30,6 +30,10 @@ public class PackageRelationshipCollection : IEnumerator
* Package relationships ordered by type.
*/
private SortedList relationshipsByType;
+ /**
+ * A lookup of internal relationships to avoid
+ */
+ private SortedList internalRelationshipsByTargetName;
/**
* This relationshipPart.
@@ -62,6 +66,7 @@ public PackageRelationshipCollection()
{
relationshipsByID = new SortedList();
relationshipsByType = new SortedList(new DuplicateComparer());
+ internalRelationshipsByTargetName = new SortedList();
}
class DuplicateComparer : IComparer
{
@@ -195,6 +200,10 @@ private static PackagePartName GetRelationshipPartName(PackagePart part)
*/
public void AddRelationship(PackageRelationship relPart)
{
+ if (relPart == null || string.IsNullOrEmpty(relPart.Id))
+ {
+ throw new ArgumentException("invalid relationship part/id");
+ }
relationshipsByID[relPart.Id] = relPart;
relationshipsByType[relPart.RelationshipType] = relPart;
}
@@ -235,6 +244,10 @@ public void AddRelationship(PackageRelationship relPart)
sourcePart, targetUri, targetMode, relationshipType, id);
relationshipsByID[rel.Id] = rel;
relationshipsByType[rel.RelationshipType] = rel;
+ if (targetMode == TargetMode.Internal)
+ {
+ internalRelationshipsByTargetName.Add(targetUri.OriginalString, rel);
+ }
return rel;
}
@@ -257,6 +270,8 @@ public void RemoveRelationship(String id)
if (relationshipsByType.Values[i] == rel)
relationshipsByType.RemoveAt(i);
}
+
+ internalRelationshipsByTargetName.RemoveAt(internalRelationshipsByTargetName.IndexOfValue(rel));
}
}
}
@@ -338,7 +353,7 @@ private void ParseRelationshipsPart(PackagePart relPart)
// Check OPC compliance M4.1 rule
bool fCorePropertiesRelationship = false;
- ///xmlRelationshipsDoc.ChildNodes.GetEnumerator();
+ //xmlRelationshipsDoc.ChildNodes.GetEnumerator();
XPathNavigator xpathnav = xmlRelationshipsDoc.CreateNavigator();
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xpathnav.NameTable);
nsMgr.AddNamespace("x", PackageNamespaces.RELATIONSHIPS);
@@ -451,8 +466,15 @@ public void Clear()
{
relationshipsByID.Clear();
relationshipsByType.Clear();
+ internalRelationshipsByTargetName.Clear();
+ }
+ public PackageRelationship FindExistingInternalRelation(PackagePart packagePart)
+ {
+ var pn=packagePart.PartName.Name;
+ if (!internalRelationshipsByTargetName.ContainsKey(pn))
+ return null;
+ return internalRelationshipsByTargetName[pn];
}
-
public override String ToString()
{
String str;
diff --git a/openxml4Net/Properties/AssemblyInfo.cs b/openxml4Net/Properties/AssemblyInfo.cs
index 429c9a8a4..eb6e36ed4 100644
--- a/openxml4Net/Properties/AssemblyInfo.cs
+++ b/openxml4Net/Properties/AssemblyInfo.cs
@@ -33,8 +33,8 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.5.5.0")]
-[assembly: AssemblyFileVersion("2.5.5.0")]
+[assembly: AssemblyVersion("2.6.0.0")]
+[assembly: AssemblyFileVersion("2.6.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0.0")]
#if NETSTANDARD2_1 || NETSTANDARD2_0 || NET40
[assembly: AllowPartiallyTrustedCallers]
diff --git a/openxml4Net/Util/XmlHelper.cs b/openxml4Net/Util/XmlHelper.cs
index d084f1b8d..c18f12cc8 100644
--- a/openxml4Net/Util/XmlHelper.cs
+++ b/openxml4Net/Util/XmlHelper.cs
@@ -176,7 +176,7 @@ public static double ReadDouble(XmlAttribute attr)
else
{
double v;
- if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out v))
+ if (double.TryParse(s, NumberStyles.Number|NumberStyles.Float| NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out v))
{
return v;
}
@@ -312,9 +312,9 @@ public static void WriteAttribute(StreamWriter sw, string attributeName, bool va
{
WriteAttribute(sw, attributeName, value, true);
}
- public static void WriteAttribute(StreamWriter sw, string attributeName, bool value, bool writeIfBlank)
+ public static void WriteAttribute(StreamWriter sw, string attributeName, bool value, bool writeIfBlank, bool defaultValue = false)
{
- if (value == false && !writeIfBlank)
+ if (value == defaultValue && !writeIfBlank)
return;
WriteAttribute(sw, attributeName, value ? "1" : "0");
}
@@ -339,13 +339,28 @@ public static void WriteAttribute(StreamWriter sw, string attributeName, int val
{
WriteAttribute(sw, attributeName, value, false);
}
+ public static void WriteAttribute(StreamWriter sw, string attributeName, uint value, bool writeIfBlank)
+ {
+ if (value == 0 && !writeIfBlank)
+ return;
+
+ WriteAttribute(sw, attributeName, value.ToString(CultureInfo.InvariantCulture));
+ }
+ public static void WriteAttribute(StreamWriter sw, string attributeName, uint value)
+ {
+ WriteAttribute(sw, attributeName, value, false);
+ }
public static void WriteAttribute(StreamWriter sw, string attributeName, string value)
{
WriteAttribute(sw, attributeName, value, false);
}
public static void WriteAttribute(StreamWriter sw, string attributeName, string value, bool writeIfBlank)
{
- if (string.IsNullOrEmpty(value) && !writeIfBlank)
+ WriteAttribute(sw, attributeName, value, writeIfBlank, string.Empty);
+ }
+ public static void WriteAttribute(StreamWriter sw, string attributeName, string value, bool writeIfBlank, string defaultValue)
+ {
+ if ((string.IsNullOrEmpty(value) || defaultValue.Equals(value)) && !writeIfBlank)
return;
sw.Write(string.Format(" {0}=\"{1}\"", attributeName, value == null ? string.Empty : EncodeXml(value)));
}
@@ -356,26 +371,22 @@ public static void WriteAttribute(StreamWriter sw, string attributeName, byte[]
WriteAttribute(sw, attributeName, BitConverter.ToString(value).Replace("-", ""), false);
}
+
public static void WriteAttribute(StreamWriter sw, string attributeName, uint value, uint defaultValue, bool writeIfBlank = false)
{
if(value != defaultValue)
- WriteAttribute(sw, attributeName, (int)value, true);
+ WriteAttribute(sw, attributeName, value, true);
else if(writeIfBlank)
- WriteAttribute(sw, attributeName, (int)value, writeIfBlank);
- }
- public static void WriteAttribute(StreamWriter sw, string attributeName, uint value, bool writeIfBlank = false)
- {
- WriteAttribute(sw, attributeName, (int)value, writeIfBlank);
+ WriteAttribute(sw, attributeName, value, writeIfBlank);
}
public static void WriteAttribute(StreamWriter sw, string attributeName, DateTime? value)
{
if (value == null)
return;
- WriteAttribute(sw, attributeName, value.ToString(), false);
- //how to write xsd:datetime data
- throw new NotImplementedException();
+ WriteAttribute(sw, attributeName, value.Value.ToString("yyyy-MM-ddTHH:mm:ss"), false);
}
+
public static void LoadXmlSafe(XmlDocument xmlDoc, Stream stream)
{
XmlReaderSettings settings = new XmlReaderSettings();
diff --git a/openxml4Net/packages.config b/openxml4Net/packages.config
index c8abe76cc..04ff7ff2c 100644
--- a/openxml4Net/packages.config
+++ b/openxml4Net/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/testcases/main/HSSF/Model/TestFormulaParser.cs b/testcases/main/HSSF/Model/TestFormulaParser.cs
index 69b655a8f..0ec96af3a 100644
--- a/testcases/main/HSSF/Model/TestFormulaParser.cs
+++ b/testcases/main/HSSF/Model/TestFormulaParser.cs
@@ -1239,9 +1239,9 @@ public void TestParseArray()
Assert.AreEqual("{1,2,2,#REF!;FALSE,3,3,2}", ptgs[0].ToFormulaString());
ArrayPtg aptg = (ArrayPtg)ptgs[0];
- Object[][] values = aptg.GetTokenArrayValues();
- Assert.AreEqual(ErrorConstant.ValueOf(FormulaError.REF.Code), values[0][3]);
- Assert.AreEqual(false, values[1][0]);
+ Object[,] values = aptg.GetTokenArrayValues();
+ Assert.AreEqual(ErrorConstant.ValueOf(FormulaError.REF.Code), values[0,3]);
+ Assert.AreEqual(false, values[1,0]);
}
[Test]
public void TestParseStringElementInArray()
@@ -1249,7 +1249,7 @@ public void TestParseStringElementInArray()
Ptg[] ptgs;
ptgs = ParseFormula("MAX({\"5\"},3)");
ConfirmTokenClasses(ptgs, typeof(ArrayPtg), typeof(IntPtg), typeof(FuncVarPtg));
- object element = ((ArrayPtg)ptgs[0]).GetTokenArrayValues()[0][0];
+ object element = ((ArrayPtg)ptgs[0]).GetTokenArrayValues()[0,0];
if (element is UnicodeString)
{
// this would cause ClassCastException below
@@ -1290,14 +1290,14 @@ public void TestParseArrayNegativeElement()
throw e;
}
ConfirmTokenClasses(ptgs, typeof(ArrayPtg));
- Object element = ((ArrayPtg)ptgs[0]).GetTokenArrayValues()[0][0];
+ Object element = ((ArrayPtg)ptgs[0]).GetTokenArrayValues()[0,0];
Assert.AreEqual(-42.0, (Double)element, 0.0);
// Should be able to handle whitespace between unary minus and digits (Excel
// accepts this formula after presenting the user with a Confirmation dialog).
ptgs = ParseFormula("{- 5}");
- element = ((ArrayPtg)ptgs[0]).GetTokenArrayValues()[0][0];
+ element = ((ArrayPtg)ptgs[0]).GetTokenArrayValues()[0,0];
Assert.AreEqual(-5.0, (Double)element, 0.0);
}
[Test]
diff --git a/testcases/main/HSSF/Record/TestNameRecord.cs b/testcases/main/HSSF/Record/TestNameRecord.cs
index 1e64d0d4f..332350090 100644
--- a/testcases/main/HSSF/Record/TestNameRecord.cs
+++ b/testcases/main/HSSF/Record/TestNameRecord.cs
@@ -698,9 +698,9 @@ private void assert_bug50244(NameRecord nr)
ArrayPtg arr = (ArrayPtg)ptg[0];
Assert.AreEqual(696, arr.RowCount);
Assert.AreEqual(1, arr.ColumnCount);
- Object[][] vals = arr.GetTokenArrayValues();
- Assert.AreEqual("1.T20.001", vals[0][0]);
- Assert.AreEqual("1.T20.010", vals[vals.Length - 1][0]);
+ Object[,] vals = arr.GetTokenArrayValues();
+ Assert.AreEqual("1.T20.001", vals[0,0]);
+ Assert.AreEqual("1.T20.010", vals[vals.Length - 1,0]);
}
[Test]
public void TestBug57923()
diff --git a/testcases/main/HSSF/UserModel/TestBugs.cs b/testcases/main/HSSF/UserModel/TestBugs.cs
index be176cd74..1c6ed5e6c 100644
--- a/testcases/main/HSSF/UserModel/TestBugs.cs
+++ b/testcases/main/HSSF/UserModel/TestBugs.cs
@@ -3485,5 +3485,33 @@ public void Test53564()
//fos.Close();
wb.Close();
}
+
+
+ // follow https://svn.apache.org/viewvc?view=revision&revision=1896552 to write a unit test for this fix.
+ [Test]
+ public void Test52447()
+ {
+ IWorkbook wb=null;
+ try
+ {
+ wb = HSSFTestDataSamples.OpenSampleWorkbook("52447.xls");
+ } catch {
+ Assert.IsNotNull(wb);
+ }
+ }
+
+ [Test]
+ public void TestAmazonDownloadFile()
+ {
+ IWorkbook wb = null;
+ try
+ {
+ wb = HSSFTestDataSamples.OpenSampleWorkbook("ca_apparel_browse_tree_guide._TTH_.xls");
+ }
+ catch
+ {
+ Assert.IsNotNull(wb);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/testcases/main/HSSF/UserModel/TestDataValidation.cs b/testcases/main/HSSF/UserModel/TestDataValidation.cs
index 62b2c8f8d..428f97078 100644
--- a/testcases/main/HSSF/UserModel/TestDataValidation.cs
+++ b/testcases/main/HSSF/UserModel/TestDataValidation.cs
@@ -50,7 +50,7 @@ public void AssertDataValidation(IWorkbook wb)
MemoryStream baos = new MemoryStream(22000);
try
{
- wb.Write(baos);
+ wb.Write(baos, false);
baos.Close();
}
catch (IOException e)
@@ -165,7 +165,7 @@ public void TestAddToExistingSheet()
MemoryStream baos = new MemoryStream();
try
{
- wb.Write(baos);
+ wb.Write(baos, false);
}
catch (IOException e)
{
diff --git a/testcases/main/HSSF/UserModel/TestHSSFDateUtil.cs b/testcases/main/HSSF/UserModel/TestHSSFDateUtil.cs
index 527d242ab..f17393232 100644
--- a/testcases/main/HSSF/UserModel/TestHSSFDateUtil.cs
+++ b/testcases/main/HSSF/UserModel/TestHSSFDateUtil.cs
@@ -489,7 +489,7 @@ public void AbsoluteDayYearTooLow()
HSSFDateUtil.AbsoluteDay(calendar, false);
Assert.Fail("Should fail here");
}
- catch (ArgumentException e)
+ catch (ArgumentException )
{
// expected here
}
@@ -500,7 +500,7 @@ public void AbsoluteDayYearTooLow()
HSSFDateUtil.AbsoluteDay(calendar, true);
Assert.Fail("Should fail here");
}
- catch (ArgumentException e)
+ catch (ArgumentException )
{
// expected here
}
diff --git a/testcases/main/HSSF/UserModel/TestHSSFSheet.cs b/testcases/main/HSSF/UserModel/TestHSSFSheet.cs
index 856723e3c..e9ee8f5d3 100644
--- a/testcases/main/HSSF/UserModel/TestHSSFSheet.cs
+++ b/testcases/main/HSSF/UserModel/TestHSSFSheet.cs
@@ -696,9 +696,8 @@ public void TestTopRow()
/** cell with formula becomes null on cloning a sheet*/
[Test]
- public new void Test35084()
+ public void Test35084()
{
-
HSSFWorkbook wb = new HSSFWorkbook();
NPOI.SS.UserModel.ISheet s = wb.CreateSheet("Sheet1");
IRow r = s.CreateRow(0);
@@ -1066,18 +1065,15 @@ public void TestLongSheetNames()
HSSFWorkbook wb = new HSSFWorkbook();
String SAME_PREFIX = "A123456789B123456789C123456789"; // 30 chars
- wb.CreateSheet(SAME_PREFIX + "Dxxxx");
try
{
wb.CreateSheet(SAME_PREFIX + "Dyyyy"); // identical up to the 32nd char
- throw new AssertionException("Expected exception not thrown");
+ Assert.Fail("Expected exception not thrown");
}
catch (ArgumentException e)
{
- Assert.AreEqual("The workbook already contains a sheet named 'A123456789B123456789C123456789Dyyyy'", e.Message);
+ Assert.IsTrue(e.Message.StartsWith("sheetName 'A123456789B123456789C123456789Dyyyy' is invalid"));
}
- wb.CreateSheet(SAME_PREFIX + "Exxxx"); // OK - differs in the 31st char
-
wb.Close();
}
/**
diff --git a/testcases/main/HSSF/UserModel/TestHSSFWorkbook.cs b/testcases/main/HSSF/UserModel/TestHSSFWorkbook.cs
index 70100b06e..1837bb22f 100644
--- a/testcases/main/HSSF/UserModel/TestHSSFWorkbook.cs
+++ b/testcases/main/HSSF/UserModel/TestHSSFWorkbook.cs
@@ -657,7 +657,7 @@ public void Bug47920()
ClassID clsid1 = fs1.Root.StorageClsid;
MemoryStream out1 = new MemoryStream(4096);
- wb.Write(out1);
+ wb.Write(out1, false);
byte[] bytes = out1.ToArray();
POIFSFileSystem fs2 = new POIFSFileSystem(new MemoryStream(bytes));
ClassID clsid2 = fs2.Root.StorageClsid;
@@ -1173,7 +1173,7 @@ public void Bug54500()
Assert.AreEqual("ASheet!A1", name.RefersToFormula);
MemoryStream stream = new MemoryStream();
- wb.Write(stream);
+ wb.Write(stream, false);
assertSheetOrder(wb, "Sheet1", "Sheet2", "Sheet3", "ASheet");
Assert.AreEqual("ASheet!A1", name.RefersToFormula);
@@ -1184,7 +1184,7 @@ public void Bug54500()
Assert.AreEqual("ASheet!A1", name.RefersToFormula);
MemoryStream stream2 = new MemoryStream();
- wb.Write(stream2);
+ wb.Write(stream2, false);
assertSheetOrder(wb, "Sheet1", "Sheet3", "ASheet");
Assert.AreEqual("ASheet!A1", name.RefersToFormula);
@@ -1295,7 +1295,7 @@ public void TestRewriteFileBug58480()
private void WriteAndCloseWorkbook(IWorkbook workbook, FileInfo file)
{
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
- workbook.Write(bytesOut);
+ workbook.Write(bytesOut, false);
workbook.Close();
byte[] byteArray = bytesOut.ToByteArray();
@@ -1359,7 +1359,7 @@ public void InvalidInPlaceWrite()
wb.Write();
Assert.Fail("Shouldn't work for new files");
}
- catch (InvalidOperationException e) { }
+ catch (InvalidOperationException) { }
// Can't work for InputStream opened files
wb = new HSSFWorkbook(
@@ -1369,7 +1369,7 @@ public void InvalidInPlaceWrite()
wb.Write();
Assert.Fail("Shouldn't work for InputStream");
}
- catch (InvalidOperationException e) { }
+ catch (InvalidOperationException) { }
// Can't work for OPOIFS
OPOIFSFileSystem ofs = new OPOIFSFileSystem(
@@ -1380,7 +1380,7 @@ public void InvalidInPlaceWrite()
wb.Write();
Assert.Fail("Shouldn't work for OPOIFSFileSystem");
}
- catch (InvalidOperationException e) { }
+ catch (InvalidOperationException) { }
// Can't work for Read-Only files
NPOIFSFileSystem fs = new NPOIFSFileSystem(
@@ -1391,7 +1391,7 @@ public void InvalidInPlaceWrite()
wb.Write();
Assert.Fail("Shouldn't work for Read Only");
}
- catch (InvalidOperationException e) { }
+ catch (InvalidOperationException) { }
}
[Test]
diff --git a/testcases/main/HSSF/UserModel/TestMatrixFormulasFromBinarySpreadsheet.cs b/testcases/main/HSSF/UserModel/TestMatrixFormulasFromBinarySpreadsheet.cs
new file mode 100644
index 000000000..3081a048d
--- /dev/null
+++ b/testcases/main/HSSF/UserModel/TestMatrixFormulasFromBinarySpreadsheet.cs
@@ -0,0 +1,187 @@
+using NPOI.HSSF.UserModel;
+using NPOI.SS.Formula.Eval;
+using NPOI.SS.UserModel;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TestCases.HSSF.UserModel
+{
+ [TestFixture]
+ public class TestMatrixFormulasFromBinarySpreadsheet
+ {
+ private static HSSFWorkbook workbook;
+ private static ISheet sheet;
+ private static IFormulaEvaluator evaluator;
+
+ private static class Navigator
+ {
+ /**
+ * Name of the test spreadsheet (found in the standard test data folder)
+ */
+ public const String FILENAME = "MatrixFormulaEvalTestData.xls";
+ /**
+ * Row (zero-based) in the spreadsheet where operations start
+ */
+ public const int START_OPERATORS_ROW_INDEX = 1;
+ /**
+ * Column (zero-based) in the spreadsheet where operations start
+ */
+ public const int START_OPERATORS_COL_INDEX = 0;
+ /**
+ * Column (zero-based) in the spreadsheet where evaluations start
+ */
+ public const int START_RESULT_COL_INDEX = 7;
+ /**
+ * Column separation in the spreadsheet between evaluations and expected results
+ */
+ public const int COL_OFF_EXPECTED_RESULT = 3;
+ /**
+ * Row separation in the spreadsheet between operations
+ */
+ public const int ROW_OFF_NEXT_OP = 4;
+ /**
+ * Used to indicate when there are no more operations left
+ */
+ public const String END_OF_TESTS = "";
+
+ }
+
+
+ public static List