Skip to content

Commit f6a952c

Browse files
committed
Provide support for group shapes loading
- Shape handling is optimized - Group shapes loading is now available - Exception handling is improved
1 parent 813084e commit f6a952c

File tree

4 files changed

+149
-71
lines changed

4 files changed

+149
-71
lines changed

FileFormat.Words.IElements.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -582,12 +582,12 @@ public GroupShape(Shape shape1,Shape shape2)
582582
public enum ShapeType
583583
{
584584
/// <summary>
585-
/// Ellipse or Oval shape.
585+
/// Rectangle shape.
586586
/// </summary>
587587
Rectangle,
588588

589589
/// <summary>
590-
/// Ellipse or Oval shape.
590+
/// Triangle shape.
591591
/// </summary>
592592
Triangle,
593593

FileFormat.Words.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,16 @@ namespace FileFormat.Words
1313
/// </summary>
1414
public class FileFormatException : Exception
1515
{
16+
public FileFormatException(string message, Exception innerException) : base(message, innerException)
17+
{
18+
}
19+
1620
/// <summary>
1721
/// Initializes a new instance of the <see cref="FileFormatException"/> class with a specified error message and a reference to the inner exception.
1822
/// </summary>
1923
/// <param name="message">The error message that explains the reason for the exception.</param>
2024
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
21-
public FileFormatException(string message, Exception innerException) : base(message, innerException)
25+
public FileFormatException(string message, Exception innerException, object ex) : base(message, innerException)
2226
{
2327
//Do nothing
2428
}

OpenXML.Words.Data.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ internal void Insert(FF.IElement newElement, int position, Document doc)
9393
break;
9494

9595
case FF.GroupShape ffGroupShape:
96-
var wpGroupShape = _ooxmlDoc.CreateConnectedShapes(ffGroupShape);
96+
var wpGroupShape = _ooxmlDoc.CreateGroupShape(ffGroupShape);
9797
elements.ElementAt(position).InsertBeforeSelf(wpGroupShape);
9898
break;
9999
}
@@ -153,7 +153,7 @@ internal void Update(FF.IElement newElement, int position, Document doc)
153153
break;
154154

155155
case FF.GroupShape ffGroupShape:
156-
var wpGroupShape = _ooxmlDoc.CreateConnectedShapes(ffGroupShape);
156+
var wpGroupShape = _ooxmlDoc.CreateGroupShape(ffGroupShape);
157157
elements.ElementAt(position).InsertBeforeSelf(wpGroupShape);
158158
break;
159159
}
@@ -242,7 +242,7 @@ internal void Append(FF.IElement newElement, Document doc)
242242
break;
243243

244244
case FF.GroupShape ffGroupShape:
245-
var wpGroupShape = _ooxmlDoc.CreateConnectedShapes(ffGroupShape);
245+
var wpGroupShape = _ooxmlDoc.CreateGroupShape(ffGroupShape);
246246
if (lastSectionProperties != null) staticDoc.MainDocumentPart.Document.Body.InsertBefore(wpGroupShape, lastSectionProperties);
247247
else staticDoc.MainDocumentPart.Document.Body.Append(wpGroupShape);
248248
break;

OpenXML.Words.cs

+139-65
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ internal void CreateDocument(List<FF.IElement> lst)
172172

173173
case FF.GroupShape ffGroupShape:
174174
{
175-
var para = CreateConnectedShapes(ffGroupShape);
175+
var para = CreateGroupShape(ffGroupShape);
176176
_wpBody.InsertBefore(para, sectionProperties);
177177
break;
178178
}
@@ -840,8 +840,8 @@ private A.ShapeTypeValues CreateShapeType(FF.ShapeType shapeType)
840840
}
841841
}
842842

843-
#region "Shapes with connector"
844-
internal WP.Paragraph CreateConnectedShapes(FF.GroupShape groupShape)
843+
#region "Create Group Shape with connector"
844+
internal WP.Paragraph CreateGroupShape(FF.GroupShape groupShape)
845845
{
846846
lock (_lockObject)
847847
{
@@ -1080,7 +1080,7 @@ internal WP.Paragraph CreateConnectedShapes(FF.GroupShape groupShape)
10801080
}
10811081
catch (Exception ex)
10821082
{
1083-
var errorMessage = OWD.OoxmlDocData.ConstructMessage(ex, "Create Coonected Shapes");
1083+
var errorMessage = OWD.OoxmlDocData.ConstructMessage(ex, "Create Group Shape");
10841084
throw new FileFormat.Words.FileFormatException(errorMessage, ex);
10851085
}
10861086
}
@@ -1195,9 +1195,9 @@ private DWS.WordprocessingShape CreatePartialShape(int Id, int X, int Y, int Wid
11951195
try
11961196
{
11971197
_pkgDocument = WordprocessingDocument.Open(stream, true);
1198-
1199-
if (_pkgDocument.MainDocumentPart?.Document?.Body == null) throw new FileFormat.Words.FileFormatException("Package or Document or Body is null", new NullReferenceException());
1200-
1198+
if (_pkgDocument.MainDocumentPart?.Document?.Body == null)
1199+
throw new FileFormat.Words.FileFormatException("Package or Document or Body is null",
1200+
new NullReferenceException());
12011201
OWD.OoxmlDocData.CreateInstance(_pkgDocument);
12021202

12031203
_mainPart = _pkgDocument.MainDocumentPart;
@@ -1209,31 +1209,51 @@ private DWS.WordprocessingShape CreatePartialShape(int Id, int X, int Y, int Wid
12091209

12101210
foreach (var element in _wpBody.Elements())
12111211
{
1212-
12131212
switch (element)
12141213
{
12151214
case WP.Paragraph wpPara:
1216-
{
1217-
var drawingFound = false;
1215+
{
1216+
var drawingFound = false;
12181217

1219-
foreach (var drawing in wpPara.Descendants<WP.Drawing>())
1220-
{
1221-
var image = LoadImage(drawing, sequence);
1218+
foreach (var drawing in wpPara.Descendants<WP.Drawing>())
1219+
{
1220+
var image = LoadImage(drawing, sequence);
1221+
if (image != null)
1222+
{
1223+
elements.Add(image);
1224+
sequence++;
1225+
drawingFound = true;
1226+
}
1227+
else
1228+
{
1229+
var inline = drawing.Inline;
12221230

1223-
if (image != null)
1231+
if (inline != null)
12241232
{
1225-
elements.Add(image);
1226-
sequence++;
1227-
drawingFound = true;
1228-
}
1229-
else
1230-
{
1231-
var shape = LoadShape(drawing,sequence);
1232-
if (shape != null)
1233-
{
1234-
elements.Add(shape);
1235-
sequence++;
1236-
drawingFound = true;
1233+
// Extract shape information from inline
1234+
var graphic = inline.Graphic;
1235+
var graphicData = graphic.GraphicData;
1236+
1237+
if (graphicData.Uri.Value == "http://schemas.microsoft.com/office/word/2010/wordprocessingShape")
1238+
{
1239+
var shape = LoadShape(graphicData, sequence);
1240+
if (shape != null)
1241+
{
1242+
elements.Add(shape);
1243+
sequence++;
1244+
drawingFound = true;
1245+
}
1246+
}
1247+
else if (graphicData.Uri.Value == "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup")
1248+
{
1249+
var groupShape = LoadGroupShape(graphicData, sequence);
1250+
if (groupShape != null)
1251+
{
1252+
elements.Add(groupShape);
1253+
sequence++;
1254+
drawingFound = true;
1255+
}
1256+
}
12371257
}
12381258
}
12391259
}
@@ -1243,7 +1263,6 @@ private DWS.WordprocessingShape CreatePartialShape(int Id, int X, int Y, int Wid
12431263
elements.Add(LoadParagraph(wpPara, sequence));
12441264
sequence++;
12451265
}
1246-
12471266
break;
12481267
}
12491268

@@ -1268,7 +1287,6 @@ private DWS.WordprocessingShape CreatePartialShape(int Id, int X, int Y, int Wid
12681287
elements.Add(LoadTable(wpTable, sequence));
12691288
sequence++;
12701289
break;
1271-
12721290
case WP.SectionProperties wpSection:
12731291
elements.Add(LoadSection(wpSection, sequence));
12741292
sequence++;
@@ -1278,7 +1296,6 @@ private DWS.WordprocessingShape CreatePartialShape(int Id, int X, int Y, int Wid
12781296
sequence++;
12791297
break;
12801298
}
1281-
12821299
}
12831300

12841301
return elements;
@@ -1559,56 +1576,113 @@ internal FF.Image LoadImage(WP.Drawing drawing, int sequence)
15591576
}
15601577
#endregion
15611578

1562-
internal FF.Shape LoadShape(WP.Drawing drawing, int sequence)
1579+
internal FF.Shape LoadShape(A.GraphicData graphicData, int sequence)
15631580
{
1564-
var inline = drawing.Inline;
1565-
1566-
if (inline != null)
1581+
if (graphicData.Uri.Value == "http://schemas.microsoft.com/office/word/2010/wordprocessingShape")
15671582
{
1568-
// Extract shape information from inline
1569-
var graphic = inline.Graphic;
1570-
var graphicData = graphic.GraphicData;
1571-
1572-
if (graphicData.Uri.Value == "http://schemas.microsoft.com/office/word/2010/wordprocessingShape")
1583+
var wordprocessingShape = graphicData.GetFirstChild<DWS.WordprocessingShape>();
1584+
if (wordprocessingShape != null)
15731585
{
1574-
var wordprocessingShape = graphicData.GetFirstChild<DWS.WordprocessingShape>();
1575-
if (wordprocessingShape != null)
1576-
{
1577-
// Extract position and size from shape properties
1578-
var shapeProperties = wordprocessingShape.GetFirstChild<DWS.ShapeProperties>();
1579-
var transform2D = shapeProperties.GetFirstChild<A.Transform2D>();
1586+
// Extract position and size from shape properties
1587+
var shapeProperties = wordprocessingShape.GetFirstChild<DWS.ShapeProperties>();
1588+
var transform2D = shapeProperties.GetFirstChild<A.Transform2D>();
15801589

1581-
var offset = transform2D.Offset;
1582-
var extents = transform2D.Extents;
1590+
var offset = transform2D.Offset;
1591+
var extents = transform2D.Extents;
15831592

1584-
int x = (int)(offset.X.Value / 9525); // Convert EMU to points
1585-
int y = (int)(offset.Y.Value / 9525);
1586-
int width = (int)(extents.Cx.Value / 9525);
1587-
int height = (int)(extents.Cy.Value / 9525);
1593+
int x = (int)(offset.X.Value / 9525); // Convert EMU to points
1594+
int y = (int)(offset.Y.Value / 9525);
1595+
int width = (int)(extents.Cx.Value / 9525);
1596+
int height = (int)(extents.Cy.Value / 9525);
15881597

1589-
// Determine the shape type
1590-
var presetGeometry = shapeProperties.GetFirstChild<A.PresetGeometry>();
1591-
var shapeType = FF.ShapeType.Ellipse; // Default
1598+
// Determine the shape type
1599+
var presetGeometry = shapeProperties.GetFirstChild<A.PresetGeometry>();
1600+
var shapeType = FF.ShapeType.Ellipse; // Default
15921601

1593-
if (presetGeometry.Preset == A.ShapeTypeValues.Diamond)
1594-
{
1595-
shapeType = FF.ShapeType.Diamond;
1596-
}
1597-
else if (presetGeometry.Preset == A.ShapeTypeValues.Hexagon)
1602+
1603+
shapeType = LoadShapeType(presetGeometry.Preset);
1604+
1605+
var shape = new FF.Shape(x, y, width, height, shapeType);
1606+
shape.ElementId = sequence;
1607+
1608+
// Return the shape object with extracted data
1609+
return shape;
1610+
}
1611+
}
1612+
1613+
return null;
1614+
}
1615+
1616+
private FF.ShapeType LoadShapeType(A.ShapeTypeValues shapeType)
1617+
{
1618+
if (shapeType == A.ShapeTypeValues.Rectangle)
1619+
return FF.ShapeType.Rectangle;
1620+
else if (shapeType == A.ShapeTypeValues.Triangle)
1621+
return FF.ShapeType.Triangle;
1622+
else if (shapeType == A.ShapeTypeValues.Ellipse)
1623+
return FF.ShapeType.Ellipse;
1624+
else if (shapeType == A.ShapeTypeValues.Diamond)
1625+
return FF.ShapeType.Diamond;
1626+
else if (shapeType == A.ShapeTypeValues.Hexagon)
1627+
return FF.ShapeType.Hexagone;
1628+
else
1629+
return FF.ShapeType.Ellipse;
1630+
}
1631+
1632+
internal FF.GroupShape LoadGroupShape(A.GraphicData graphicData, int sequence)
1633+
{
1634+
lock (_lockObject)
1635+
{
1636+
try
1637+
{
1638+
1639+
if (graphicData.Uri.Value == "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup")
1640+
{
1641+
var wordprocessingShapes = graphicData.Descendants<DWS.WordprocessingShape>();//.GetFirstChild<DWS.WordprocessingShape>();
1642+
if (wordprocessingShapes != null)
15981643
{
1599-
shapeType = FF.ShapeType.Hexagone;
1600-
}
1601-
var shape = new FF.Shape(x, y, width, height, shapeType);
1602-
shape.ElementId = sequence;
1644+
var count = 0;
1645+
var listShapes = new List<FF.Shape>();
1646+
foreach (var wpShape in wordprocessingShapes)
1647+
{
1648+
var shapeProperties = wpShape.GetFirstChild<DWS.ShapeProperties>();
1649+
var presetGeometry = shapeProperties.GetFirstChild<A.PresetGeometry>();
1650+
var shapeType = FF.ShapeType.Ellipse;
16031651

1604-
// Return the shape object with extracted data
1605-
return shape;
1652+
if (presetGeometry.Preset != A.ShapeTypeValues.BentConnector3)
1653+
{
1654+
count = count + 1;
1655+
var transform2D = shapeProperties.GetFirstChild<A.Transform2D>();
1656+
1657+
var offset = transform2D.Offset;
1658+
var extents = transform2D.Extents;
1659+
1660+
int x = (int)(offset.X.Value / 9525); // Convert EMU to points
1661+
int y = (int)(offset.Y.Value / 9525);
1662+
int width = (int)(extents.Cx.Value / 9525);
1663+
int height = (int)(extents.Cy.Value / 9525);
1664+
shapeType = LoadShapeType(presetGeometry.Preset);
1665+
var shape = new FF.Shape(x, y, width, height, shapeType);
1666+
shape.ElementId = sequence * 50 + count;
1667+
listShapes.Add(shape);
1668+
}
1669+
}
1670+
var groupShape = new FF.GroupShape(listShapes[0], listShapes[1]);
1671+
groupShape.ElementId = sequence;
1672+
return groupShape;
1673+
}
16061674
}
1675+
return null;
1676+
}
1677+
catch (Exception ex)
1678+
{
1679+
var errorMessage = OWD.OoxmlDocData.ConstructMessage(ex, "Load Group Shape");
1680+
throw new FileFormat.Words.FileFormatException(errorMessage, ex);
16071681
}
16081682
}
1609-
return null;
16101683
}
16111684

1685+
16121686
#region Load OpenXML Table
16131687
internal FF.Table LoadTable(WP.Table wpTable, int id)
16141688
{

0 commit comments

Comments
 (0)