Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion OpenXmlFormats/Wordprocessing/Numbering.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1100,7 +1100,7 @@ public bool ValueEquals(CT_AbstractNum cT_AbstractNum)
public void Set(CT_AbstractNum cT_AbstractNum)
{
this.abstractNumIdField = cT_AbstractNum.abstractNumIdField;
this.lvlField = new List<CT_Lvl>(cT_AbstractNum.lvlField);
this.lvlField = cT_AbstractNum.lvlField == null ? new List<CT_Lvl>() : new List<CT_Lvl>(cT_AbstractNum.lvlField);
this.multiLevelTypeField = cT_AbstractNum.multiLevelTypeField;
this.nameField = cT_AbstractNum.nameField;
this.nsidField = cT_AbstractNum.nsidField;
Expand Down
16 changes: 16 additions & 0 deletions OpenXmlFormats/Wordprocessing/Table.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2900,6 +2900,22 @@ public CT_TblPPr AddNewTblPPr()
this.tblpPr = new CT_TblPPr();
return this.tblpPr;
}

public bool IsSetJc()
{
return this.jc != null;
}

public CT_Jc AddNewJc()
{
this.jc = new CT_Jc();
return this.jc;
}

public void UnsetJc()
{
this.jc = null;
}
}


Expand Down
59 changes: 59 additions & 0 deletions ooxml/XWPF/Usermodel/TableRowAlign.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace NPOI.XWPF.UserModel
{
/// <summary>
/// Sets alignment values allowed for Tables and Table Rows
/// </summary>
public enum TableRowAlign
{

LEFT = 0,
CENTER = 1,
RIGHT = 2
}
public static class TableRowAlignExtension
{
private static readonly Dictionary<int, TableRowAlign> imap =
new(){
{ 0, TableRowAlign.LEFT },
{ 1, TableRowAlign.CENTER },
{ 2, TableRowAlign.RIGHT },
};

public static TableRowAlign ValueOf(int type)
{
if(imap.TryGetValue(type, out TableRowAlign err))
return err;
throw new ArgumentException("Unknown table row alignment: " + type);
}

public static int GetValue(this TableRowAlign trAlign)
{
return (int) trAlign;
}
}
}


13 changes: 9 additions & 4 deletions ooxml/XWPF/Usermodel/XWPFNumbering.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace NPOI.XWPF.UserModel
using System.IO;
using System.Xml.Serialization;
using System.Xml;
using NPOI.Util;


/**
Expand Down Expand Up @@ -302,11 +303,15 @@ public string AddAbstractNum()
*/
public bool RemoveAbstractNum(string abstractNumID)
{
if (int.Parse(abstractNumID) < abstractNums.Count)
foreach (XWPFAbstractNum abstractNum in abstractNums)
{
ctNumbering.RemoveAbstractNum(int.Parse(abstractNumID));
abstractNums.RemoveAt(int.Parse(abstractNumID));
return true;
string foundNumId = abstractNum.GetAbstractNum().abstractNumId;
if(abstractNumID.Equals(foundNumId))
{
ctNumbering.RemoveAbstractNum(int.Parse(foundNumId));
abstractNums.Remove(abstractNum);
return true;
}
}
return false;
}
Expand Down
9 changes: 8 additions & 1 deletion ooxml/XWPF/Usermodel/XWPFSDTContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public class XWPFSDTContent : ISDTContent

public XWPFSDTContent(CT_SdtContentRun sdtRun, IBody part, IRunBody parent)
{
if (sdtRun == null)
{
return;
}
foreach (CT_R ctr in sdtRun.GetRList())
{
XWPFRun run = new XWPFRun((CT_R)ctr, parent);
Expand All @@ -51,7 +55,10 @@ public XWPFSDTContent(CT_SdtContentRun sdtRun, IBody part, IRunBody parent)
}
public XWPFSDTContent(CT_SdtContentBlock block, IBody part, IRunBody parent)
{

if (block == null)
{
return;
}
foreach (object o in block.Items)
{
if (o is CT_P ctP)
Expand Down
56 changes: 56 additions & 0 deletions ooxml/XWPF/Usermodel/XWPFTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,62 @@ public CT_TblPr GetTrPr()
.AddNewTblPr();
}

/// <summary>
/// Returns CTTblPr object for table. Creates it if it does not exist.
/// </summary>
private CT_TblPr GetTblPr() {
return GetTblPr(true);
}

/// <summary>
/// Returns CTTblPr object for table. If force parameter is true, will
/// create the element if necessary. If force parameter is false, returns
/// null when CTTblPr element is missing.
/// </summary>
/// <param name="force">- force creation of CTTblPr element if necessary</param>
private CT_TblPr GetTblPr(bool force)
{
return (ctTbl.tblPr != null) ? ctTbl.tblPr
: (force ? ctTbl.AddNewTblPr() : null);
}

/// <summary>
/// Get or set the current table alignment or NULL
/// </summary>
/// <returns>Table Alignment as a <see cref="TableRowAlign"/> enum</returns>
public TableRowAlign? TableAlignment
{
get
{
CT_TblPr tPr = GetTblPr(false);
return tPr == null ? null
: tPr.IsSetJc() ? TableRowAlignExtension.ValueOf((int)tPr.jc.val)
: null;
}
set
{
if(value.HasValue)
{
CT_TblPr tPr = GetTblPr(true);
CT_Jc jc = tPr.IsSetJc() ? tPr.jc : tPr.AddNewJc();
jc.val = (ST_Jc)value.Value.GetValue();
}
else
{
RemoveTableAlignment();
}
}
}

/// <summary>
/// Removes the table alignment attribute from a table
/// </summary>
public void RemoveTableAlignment() {
CT_TblPr tPr = GetTblPr(false);
if (tPr != null && tPr.IsSetJc()) {
tPr.UnsetJc();
}
}
private static void AddColumn(XWPFTableRow tabRow, int sizeCol)
{
if (sizeCol > 0)
Expand Down
51 changes: 51 additions & 0 deletions testcases/ooxml/XWPF/TestXWPFBugs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,57 @@ public void Test59378()
XWPFDocument docBack = XWPFTestDataSamples.WriteOutAndReadBack(doc);
docBack.Close();
}

[Test]
public void Test63788() {
using (XWPFDocument doc = new XWPFDocument())
{

XWPFNumbering numbering = doc.CreateNumbering();

for (int i = 10; i >= 0; i--) {
addNumberingWithAbstractId(numbering, i); //add numbers in reverse order
}

for (int i = 0; i <= 10; i++) {
ClassicAssert.AreEqual(i, int.Parse(numbering.GetAbstractNum(i.ToString()).GetAbstractNum().abstractNumId));
}

//attempt to remove item with numId 2
ClassicAssert.IsTrue(numbering.RemoveAbstractNum("2"));

for (int i = 0; i <= 10; i++) {
XWPFAbstractNum abstractNum = numbering.GetAbstractNum(i.ToString());

// we removed id "2", so this one should be empty, all others not
if (i == 2) {
ClassicAssert.IsNull(abstractNum, "Failed for " + i);
} else {
ClassicAssert.IsNotNull(abstractNum, "Failed for " + i);
ClassicAssert.AreEqual(i, int.Parse(abstractNum.GetAbstractNum().abstractNumId));
}
}

// removing the same again fails
ClassicAssert.IsFalse(numbering.RemoveAbstractNum("2"));

// removing another one works
ClassicAssert.IsTrue(numbering.RemoveAbstractNum("4"));
}
}

private static void addNumberingWithAbstractId(XWPFNumbering documentNumbering, int id)
{
// create a numbering scheme
CT_AbstractNum cTAbstractNum = new CT_AbstractNum();
// give the scheme an ID
cTAbstractNum.abstractNumId = id.ToString();

XWPFAbstractNum abstractNum = new XWPFAbstractNum(cTAbstractNum);
string abstractNumID = documentNumbering.AddAbstractNum(abstractNum);

documentNumbering.AddNum(abstractNumID);
}
}
}

14 changes: 14 additions & 0 deletions testcases/ooxml/XWPF/UserModel/TestXWPFSDT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,20 @@ public void Test60341()
ClassicAssert.AreEqual("", sdts[0].GetTitle());
}

[Test]
public void Test62859()
{
//this doesn't test the exact code path for this issue, but
//it does test for a related issue, and the fix fixes both.
//We should try to add the actual triggering document
//to our test suite.
XWPFDocument doc = XWPFTestDataSamples.OpenSampleDocument("Bug62859.docx");
List<AbstractXWPFSDT> sdts = ExtractAllSDTs(doc);
ClassicAssert.AreEqual(1, sdts.Count);
ClassicAssert.AreEqual("", sdts[0].GetTag());
ClassicAssert.AreEqual("", sdts[0].GetTitle());
}

private List<AbstractXWPFSDT> ExtractAllSDTs(XWPFDocument doc)
{

Expand Down
44 changes: 29 additions & 15 deletions testcases/ooxml/XWPF/UserModel/TestXWPFTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,21 @@ limitations under the License.
==================================================================== */
namespace TestCases.XWPF.UserModel
{
using System;
using NUnit.Framework;using NUnit.Framework.Legacy;
using NPOI.OpenXmlFormats.Wordprocessing;
using System.Collections.Generic;
using NPOI.XWPF.UserModel;
using NUnit.Framework;
using NUnit.Framework.Legacy;
using System;
using System.Collections.Generic;
using System.IO;


/**
* Tests for XWPF Run
* Tests for XWPF Tables
*/
[TestFixture]
public class TestXWPFTable
{
[SetUp]
public void SetUp()
{
/*
XWPFDocument doc = new XWPFDocument();
p = doc.CreateParagraph();

this.ctRun = CTR.Factory.NewInstance();
*/
}

[Test]
public void TestConstructor()
{
Expand Down Expand Up @@ -346,5 +337,28 @@ public void TestReadTableCaptionAndDescription()
ClassicAssert.AreEqual("Table Title", table.TableCaption);
ClassicAssert.AreEqual("Table Description", table.TableDescription);
}

[Test]
public void TestSetGetTableAlignment()
{
XWPFDocument doc = new XWPFDocument();
XWPFTable tbl = doc.CreateTable(1, 1);
tbl.TableAlignment = (TableRowAlign.LEFT);
ClassicAssert.AreEqual(TableRowAlign.LEFT, tbl.TableAlignment);
tbl.TableAlignment = (TableRowAlign.CENTER);
ClassicAssert.AreEqual(TableRowAlign.CENTER, tbl.TableAlignment);
tbl.TableAlignment = (TableRowAlign.RIGHT);
ClassicAssert.AreEqual(TableRowAlign.RIGHT, tbl.TableAlignment);
tbl.RemoveTableAlignment();
ClassicAssert.IsNull(tbl.TableAlignment);
try
{
doc.Close();
}
catch (IOException e)
{
ClassicAssert.Fail("Unable to close doc");
}
}
}
}
Binary file added testcases/test-data/document/Bug62859.docx
Binary file not shown.
Loading