diff --git a/ClosedXML/Excel/Drawings/IXLMarker.cs b/ClosedXML/Excel/Drawings/IXLMarker.cs
index 3f2bb92..d5c2ef4 100644
--- a/ClosedXML/Excel/Drawings/IXLMarker.cs
+++ b/ClosedXML/Excel/Drawings/IXLMarker.cs
@@ -1,15 +1,10 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+using System.Drawing;
namespace ClosedXML.Excel.Drawings
{
internal interface IXLMarker
{
- Int32 ColumnId { get; set; }
- Int32 RowId { get; set; }
- Double ColumnOffset { get; set; }
- Double RowOffset { get; set; }
+ IXLAddress Address { get; set; }
+ Point Offset { get; set; }
}
}
diff --git a/ClosedXML/Excel/Drawings/IXLPicture.cs b/ClosedXML/Excel/Drawings/IXLPicture.cs
index a4e0c48..d059776 100644
--- a/ClosedXML/Excel/Drawings/IXLPicture.cs
+++ b/ClosedXML/Excel/Drawings/IXLPicture.cs
@@ -1,11 +1,12 @@
using System;
+using System.Drawing;
using System.IO;
namespace ClosedXML.Excel.Drawings
{
public interface IXLPicture : IDisposable
{
- IXLCell BottomRightCell { get; }
+ IXLAddress BottomRightCellAddress { get; }
///
/// Type of image. The supported formats are defined by OpenXML's ImagePartType.
@@ -13,29 +14,42 @@
///
XLPictureFormat Format { get; }
- long Height { get; set; }
+ Int32 Height { get; set; }
MemoryStream ImageStream { get; }
- long Left { get; set; }
+ Int32 Left { get; set; }
String Name { get; set; }
- long OriginalHeight { get; }
- long OriginalWidth { get; }
+ Int32 OriginalHeight { get; }
+ Int32 OriginalWidth { get; }
XLPicturePlacement Placement { get; set; }
- long Top { get; set; }
- IXLCell TopLeftCell { get; }
- long Width { get; set; }
+ Int32 Top { get; set; }
+ IXLAddress TopLeftCellAddress { get; }
+ Int32 Width { get; set; }
+ IXLWorksheet Worksheet { get; }
- IXLPicture AtPosition(long left, long top);
+ Point GetOffset(XLMarkerPosition position);
- IXLPicture AtPosition(IXLCell cell);
+ IXLPicture MoveTo(Int32 left, Int32 top);
- IXLPicture AtPosition(IXLCell fromCell, IXLCell toCell);
+ IXLPicture MoveTo(IXLAddress cell);
- void ScaleHeight(Double factor, Boolean relativeToOriginal = false);
+ IXLPicture MoveTo(IXLAddress cell, Int32 xOffset, Int32 yOffset);
- void ScaleWidth(Double factor, Boolean relativeToOriginal = false);
+ IXLPicture MoveTo(IXLAddress cell, Point offset);
+
+ IXLPicture MoveTo(IXLAddress fromCell, IXLAddress toCell);
+
+ IXLPicture MoveTo(IXLAddress fromCell, Int32 fromCellXOffset, Int32 fromCellYOffset, IXLAddress toCell, Int32 toCellXOffset, Int32 toCellYOffset);
+
+ IXLPicture MoveTo(IXLAddress fromCell, Point fromOffset, IXLAddress toCell, Point toOffset);
+
+ IXLPicture Scale(Double factor, Boolean relativeToOriginal = false);
+
+ IXLPicture ScaleHeight(Double factor, Boolean relativeToOriginal = false);
+
+ IXLPicture ScaleWidth(Double factor, Boolean relativeToOriginal = false);
IXLPicture WithPlacement(XLPicturePlacement value);
- IXLPicture WithSize(long width, long height);
+ IXLPicture WithSize(Int32 width, Int32 height);
}
}
diff --git a/ClosedXML/Excel/Drawings/PictureEnums.cs b/ClosedXML/Excel/Drawings/PictureEnums.cs
index 4cd1fcf..3d76e73 100644
--- a/ClosedXML/Excel/Drawings/PictureEnums.cs
+++ b/ClosedXML/Excel/Drawings/PictureEnums.cs
@@ -1,11 +1,11 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace ClosedXML.Excel.Drawings
{
+ public enum XLMarkerPosition
+ {
+ TopLeft,
+ BottomRight
+ }
+
public enum XLPictureFormat
{
Bmp = 0,
diff --git a/ClosedXML/Excel/Drawings/XLMarker.cs b/ClosedXML/Excel/Drawings/XLMarker.cs
index 4934cad..f48bf5c 100644
--- a/ClosedXML/Excel/Drawings/XLMarker.cs
+++ b/ClosedXML/Excel/Drawings/XLMarker.cs
@@ -1,48 +1,23 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+using System.Diagnostics;
+using System.Drawing;
namespace ClosedXML.Excel.Drawings
{
+ [DebuggerDisplay("{Address} {Offset}")]
internal class XLMarker : IXLMarker
{
- private Int32 colId;
- private Int32 rowId;
+ internal XLMarker(IXLAddress address)
+ : this(address, new Point(0, 0))
+ { }
- public Int32 ColumnId
+ internal XLMarker(IXLAddress address, Point offset)
{
- set
- {
- if (value < 1 || value > XLHelper.MaxColumnNumber)
- throw new ArgumentOutOfRangeException(String.Format("Column number must be between 1 and {0}",
- XLHelper.MaxColumnNumber));
- this.colId = value;
- }
- get
- {
- return this.colId;
- }
+ this.Address = address;
+ this.Offset = offset;
}
- public Int32 RowId
- {
- set
- {
- if (value < 1 || value > XLHelper.MaxRowNumber)
- throw new ArgumentOutOfRangeException(String.Format("Row number must be between 1 and {0}",
- XLHelper.MaxRowNumber));
- this.rowId = value;
- }
- get
- {
- return this.rowId;
- }
- }
+ public IXLAddress Address { get; set; }
- public Double ColumnOffset { get; set; }
-
- public Double RowOffset { get; set; }
-
+ public Point Offset { get; set; }
}
}
diff --git a/ClosedXML/Excel/Drawings/XLPicture.cs b/ClosedXML/Excel/Drawings/XLPicture.cs
index 6cf81fc..d591f8f 100644
--- a/ClosedXML/Excel/Drawings/XLPicture.cs
+++ b/ClosedXML/Excel/Drawings/XLPicture.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
@@ -8,16 +9,13 @@
namespace ClosedXML.Excel.Drawings
{
+ [DebuggerDisplay("{Name}")]
internal class XLPicture : IXLPicture
{
private readonly IXLWorksheet _worksheet;
- private XLPicture(IXLWorksheet worksheet)
- {
- if (worksheet == null) throw new ArgumentNullException(nameof(worksheet));
- this._worksheet = worksheet;
- this.Placement = XLPicturePlacement.MoveAndSize;
- }
+ private Int32 height;
+ private Int32 width;
internal XLPicture(IXLWorksheet worksheet, Stream stream, XLPictureFormat format)
: this(worksheet)
@@ -27,6 +25,7 @@
this.ImageStream = new MemoryStream();
{
+ stream.Position = 0;
stream.CopyTo(ImageStream);
ImageStream.Seek(0, SeekOrigin.Begin);
@@ -60,43 +59,38 @@
this.Format = Enum.Parse(typeof(XLPictureFormat), formats.Single().Name, true).CastTo();
}
- public IXLCell BottomRightCell
+ private XLPicture(IXLWorksheet worksheet)
+ {
+ if (worksheet == null) throw new ArgumentNullException(nameof(worksheet));
+ this._worksheet = worksheet;
+ this.Placement = XLPicturePlacement.MoveAndSize;
+ this.Markers = new Dictionary()
+ {
+ [XLMarkerPosition.TopLeft] = null,
+ [XLMarkerPosition.BottomRight] = null
+ };
+ }
+
+ public IXLAddress BottomRightCellAddress
{
get
{
- if (this.Markers.Count > 1)
- {
- var marker = this.Markers.Skip(1).First();
- return _worksheet.Cell(marker.RowId, marker.ColumnId);
- }
- else
- return null;
+ return Markers[XLMarkerPosition.BottomRight].Address;
}
private set
{
- while (this.Markers.Count > 1)
- {
- this.Markers.RemoveAt(this.Markers.Count - 1);
- }
-
- this.Markers.Add(new XLMarker()
- {
- ColumnId = value.WorksheetColumn().ColumnNumber(),
- RowId = value.WorksheetRow().RowNumber()
- });
+ if (!value.Worksheet.Equals(this._worksheet))
+ throw new ArgumentOutOfRangeException(nameof(value.Worksheet));
+ this.Markers[XLMarkerPosition.BottomRight] = new XLMarker(value);
}
}
public XLPictureFormat Format { get; private set; }
- private long height;
- public long Height
+ public Int32 Height
{
- get
- {
- return height;
- }
+ get { return height; }
set
{
if (this.Placement == XLPicturePlacement.MoveAndSize)
@@ -107,73 +101,54 @@
public MemoryStream ImageStream { get; private set; }
- public long left;
-
- public long Left
+ public Int32 Left
{
- get { return left; }
+ get { return Markers[XLMarkerPosition.TopLeft]?.Offset.X ?? 0; }
set
{
if (this.Placement != XLPicturePlacement.FreeFloating)
throw new ArgumentException("To set the left-hand offset, the placement should be FreeFloating");
- left = value;
+
+ Markers[XLMarkerPosition.TopLeft] = new XLMarker(_worksheet.Cell(1, 1).Address, new Point(value, this.Top));
}
}
- public IList Markers { get; private set; } = new List();
public String Name { get; set; }
- public long OriginalHeight { get; private set; }
-
- public long OriginalWidth { get; private set; }
-
+ public Int32 OriginalHeight { get; private set; }
+ public Int32 OriginalWidth { get; private set; }
public XLPicturePlacement Placement { get; set; }
- private long top;
- public long Top
+ public Int32 Top
{
- get { return top; }
+ get { return Markers[XLMarkerPosition.TopLeft]?.Offset.Y ?? 0; }
set
{
if (this.Placement != XLPicturePlacement.FreeFloating)
throw new ArgumentException("To set the top offset, the placement should be FreeFloating");
- top = value;
+
+ Markers[XLMarkerPosition.TopLeft] = new XLMarker(_worksheet.Cell(1, 1).Address, new Point(this.Left, value));
}
}
- public IXLCell TopLeftCell
+ public IXLAddress TopLeftCellAddress
{
get
{
- if (this.Markers.Any())
- {
- var marker = this.Markers.First();
- return _worksheet.Cell(marker.RowId, marker.ColumnId);
- }
- else
- return null;
+ return Markers[XLMarkerPosition.TopLeft].Address;
}
private set
{
- if (this.Markers.Any())
- this.Markers.RemoveAt(0);
+ if (!value.Worksheet.Equals(this._worksheet))
+ throw new ArgumentOutOfRangeException(nameof(value.Worksheet));
- this.Markers.Insert(0, new XLMarker()
- {
- ColumnId = value.WorksheetColumn().ColumnNumber(),
- RowId = value.WorksheetRow().RowNumber()
- });
+ this.Markers[XLMarkerPosition.TopLeft] = new XLMarker(value);
}
}
- private long width;
-
- public long Width
+ public Int32 Width
{
- get
- {
- return width;
- }
+ get { return width; }
set
{
if (this.Placement == XLPicturePlacement.MoveAndSize)
@@ -182,7 +157,24 @@
}
}
- public IXLPicture AtPosition(long left, long top)
+ public IXLWorksheet Worksheet
+ {
+ get { return _worksheet; }
+ }
+
+ internal IDictionary Markers { get; private set; }
+
+ public void Dispose()
+ {
+ this.ImageStream.Dispose();
+ }
+
+ public Point GetOffset(XLMarkerPosition position)
+ {
+ return Markers[position].Offset;
+ }
+
+ public IXLPicture MoveTo(Int32 left, Int32 top)
{
this.Placement = XLPicturePlacement.FreeFloating;
this.Left = left;
@@ -190,39 +182,65 @@
return this;
}
- public IXLPicture AtPosition(IXLCell cell)
+ public IXLPicture MoveTo(IXLAddress cell)
+ {
+ return MoveTo(cell, 0, 0);
+ }
+
+ public IXLPicture MoveTo(IXLAddress cell, Int32 xOffset, Int32 yOffset)
+ {
+ return MoveTo(cell, new Point(xOffset, yOffset));
+ }
+
+ public IXLPicture MoveTo(IXLAddress cell, Point offset)
{
if (cell == null) throw new ArgumentNullException(nameof(cell));
this.Placement = XLPicturePlacement.Move;
- this.TopLeftCell = cell;
+ this.TopLeftCellAddress = cell;
+ this.Markers[XLMarkerPosition.TopLeft].Offset = offset;
return this;
}
- public IXLPicture AtPosition(IXLCell fromCell, IXLCell toCell)
+ public IXLPicture MoveTo(IXLAddress fromCell, IXLAddress toCell)
+ {
+ return MoveTo(fromCell, 0, 0, toCell, 0, 0);
+ }
+
+ public IXLPicture MoveTo(IXLAddress fromCell, Int32 fromCellXOffset, Int32 fromCellYOffset, IXLAddress toCell, Int32 toCellXOffset, Int32 toCellYOffset)
+ {
+ return MoveTo(fromCell, new Point(fromCellXOffset, fromCellYOffset), toCell, new Point(toCellXOffset, toCellYOffset));
+ }
+
+ public IXLPicture MoveTo(IXLAddress fromCell, Point fromOffset, IXLAddress toCell, Point toOffset)
{
if (fromCell == null) throw new ArgumentNullException(nameof(fromCell));
+ if (toCell == null) throw new ArgumentNullException(nameof(toCell));
this.Placement = XLPicturePlacement.MoveAndSize;
- this.TopLeftCell = fromCell;
- if (toCell != null)
- this.BottomRightCell = toCell;
+ this.TopLeftCellAddress = fromCell;
+ this.Markers[XLMarkerPosition.TopLeft].Offset = fromOffset;
+
+ this.BottomRightCellAddress = toCell;
+ this.Markers[XLMarkerPosition.BottomRight].Offset = toOffset;
return this;
}
- public void Dispose()
+ public IXLPicture Scale(Double factor, Boolean relativeToOriginal = false)
{
- this.ImageStream.Dispose();
+ return this.ScaleHeight(factor, relativeToOriginal).ScaleWidth(factor, relativeToOriginal);
}
- public void ScaleHeight(Double factor, Boolean relativeToOriginal = false)
+ public IXLPicture ScaleHeight(Double factor, Boolean relativeToOriginal = false)
{
- this.Height = Convert.ToInt64((relativeToOriginal ? this.OriginalHeight : this.Height) * factor);
+ this.Height = Convert.ToInt32((relativeToOriginal ? this.OriginalHeight : this.Height) * factor);
+ return this;
}
- public void ScaleWidth(Double factor, Boolean relativeToOriginal = false)
+ public IXLPicture ScaleWidth(Double factor, Boolean relativeToOriginal = false)
{
- this.Width = Convert.ToInt64((relativeToOriginal ? this.OriginalWidth : this.Width) * factor);
+ this.Width = Convert.ToInt32((relativeToOriginal ? this.OriginalWidth : this.Width) * factor);
+ return this;
}
public IXLPicture WithPlacement(XLPicturePlacement value)
@@ -231,7 +249,7 @@
return this;
}
- public IXLPicture WithSize(long width, long height)
+ public IXLPicture WithSize(Int32 width, Int32 height)
{
this.Width = width;
this.Height = height;
diff --git a/ClosedXML/Excel/XLWorkbook_Save.cs b/ClosedXML/Excel/XLWorkbook_Save.cs
index e74db1d..457ecbc 100644
--- a/ClosedXML/Excel/XLWorkbook_Save.cs
+++ b/ClosedXML/Excel/XLWorkbook_Save.cs
@@ -2590,22 +2590,22 @@
break;
case Drawings.XLPicturePlacement.MoveAndSize:
- var moveAndSizeFromMarker = pic.Markers.First();
+ var moveAndSizeFromMarker = pic.Markers[Drawings.XLMarkerPosition.TopLeft];
fMark = new Xdr.FromMarker
{
- ColumnId = new Xdr.ColumnId((moveAndSizeFromMarker.ColumnId - 1).ToString()),
- RowId = new Xdr.RowId((moveAndSizeFromMarker.RowId - 1).ToString()),
- ColumnOffset = new Xdr.ColumnOffset((moveAndSizeFromMarker.ColumnOffset + pic.Left).ToString()),
- RowOffset = new Xdr.RowOffset((moveAndSizeFromMarker.RowOffset + pic.Top).ToString())
+ ColumnId = new Xdr.ColumnId((moveAndSizeFromMarker.Address.ColumnNumber - 1).ToString()),
+ RowId = new Xdr.RowId((moveAndSizeFromMarker.Address.RowNumber - 1).ToString()),
+ ColumnOffset = new Xdr.ColumnOffset(ConvertToEnglishMetricUnits(moveAndSizeFromMarker.Offset.X, GraphicsUtils.Graphics.DpiX).ToString()),
+ RowOffset = new Xdr.RowOffset(ConvertToEnglishMetricUnits(moveAndSizeFromMarker.Offset.Y, GraphicsUtils.Graphics.DpiY).ToString())
};
- var moveAndSizeToMarker = pic.Markers.Last();
+ var moveAndSizeToMarker = pic.Markers[Drawings.XLMarkerPosition.BottomRight];
tMark = new Xdr.ToMarker
{
- ColumnId = new Xdr.ColumnId((moveAndSizeToMarker.ColumnId - 1).ToString()),
- RowId = new Xdr.RowId((moveAndSizeToMarker.RowId - 1).ToString()),
- ColumnOffset = new Xdr.ColumnOffset((moveAndSizeToMarker.ColumnOffset + pic.Left).ToString()),
- RowOffset = new Xdr.RowOffset((moveAndSizeToMarker.RowOffset + pic.Top).ToString())
+ ColumnId = new Xdr.ColumnId((moveAndSizeToMarker.Address.ColumnNumber - 1).ToString()),
+ RowId = new Xdr.RowId((moveAndSizeToMarker.Address.RowNumber - 1).ToString()),
+ ColumnOffset = new Xdr.ColumnOffset(ConvertToEnglishMetricUnits(moveAndSizeToMarker.Offset.X, GraphicsUtils.Graphics.DpiX).ToString()),
+ RowOffset = new Xdr.RowOffset(ConvertToEnglishMetricUnits(moveAndSizeToMarker.Offset.Y, GraphicsUtils.Graphics.DpiY).ToString())
};
var twoCellAnchor = new Xdr.TwoCellAnchor(
@@ -2635,13 +2635,13 @@
break;
case Drawings.XLPicturePlacement.Move:
- var moveFromMarker = pic.Markers.First();
+ var moveFromMarker = pic.Markers[Drawings.XLMarkerPosition.TopLeft];
fMark = new Xdr.FromMarker
{
- ColumnId = new Xdr.ColumnId((moveFromMarker.ColumnId - 1).ToString()),
- RowId = new Xdr.RowId((moveFromMarker.RowId - 1).ToString()),
- ColumnOffset = new Xdr.ColumnOffset((moveFromMarker.ColumnOffset + pic.Left).ToString()),
- RowOffset = new Xdr.RowOffset((moveFromMarker.RowOffset + pic.Top).ToString())
+ ColumnId = new Xdr.ColumnId((moveFromMarker.Address.ColumnNumber - 1).ToString()),
+ RowId = new Xdr.RowId((moveFromMarker.Address.RowNumber - 1).ToString()),
+ ColumnOffset = new Xdr.ColumnOffset(ConvertToEnglishMetricUnits(moveFromMarker.Offset.X + pic.Left, GraphicsUtils.Graphics.DpiX).ToString()),
+ RowOffset = new Xdr.RowOffset(ConvertToEnglishMetricUnits(moveFromMarker.Offset.Y + pic.Top, GraphicsUtils.Graphics.DpiY).ToString())
};
var oneCellAnchor = new Xdr.OneCellAnchor(
diff --git a/ClosedXML_Examples/ClosedXML_Examples.csproj b/ClosedXML_Examples/ClosedXML_Examples.csproj
index de7cb8e..16e493e 100644
--- a/ClosedXML_Examples/ClosedXML_Examples.csproj
+++ b/ClosedXML_Examples/ClosedXML_Examples.csproj
@@ -185,6 +185,9 @@
+
+
+