Skip to content
Open
2 changes: 2 additions & 0 deletions src/EPPlus/Constants/Schemas.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ internal class Schemas
internal const string schemaRichValueRel = "http://schemas.microsoft.com/office/spreadsheetml/2022/richvaluerel";
internal const string schemaWebImage = "http://schemas.microsoft.com/office/spreadsheetml/2020/richdatawebimage";
internal const string schemaDataMashup = "http://schemas.microsoft.com/DataMashup";

internal const string schemaCalcFeature = "http://schemas.microsoft.com/office/spreadsheetml/2018/calcfeatures";
}
}
34 changes: 21 additions & 13 deletions src/EPPlus/Core/RangeCopyHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -925,23 +925,27 @@ private void CopyMergedCells(Dictionary<int, ExcelAddress> copiedMergedCells)

private void CopyFullRow()
{
if (_sourceRange._fromRow == 1 && _sourceRange._toRow == ExcelPackage.MaxRows)
_sourceRange.GetAddressDimensionFullRowAndColumn(out int dimFromRow, out int dimFromCol, out int dimToRow, out int dimToCol);
if (dimFromRow == 0 && dimFromCol==0) return;
if (_sourceRange._fromRow == 1 && _sourceRange._toRow == ExcelPackage.MaxRows && dimFromCol > 0)
{
for (int col = 0; col < _sourceRange.Columns; col++)
var diff = dimFromCol - _sourceRange._fromCol;
for (int col = 0; col < (dimToCol-dimFromCol + 1); col++)
{
_destinationRange.Worksheet.Column(_destinationRange.Start.Column + col).OutlineLevel = _sourceRange.Worksheet.Column(_sourceRange._fromCol + col).OutlineLevel;
_destinationRange.Worksheet.Column(_destinationRange.Start.Column + col + diff).OutlineLevel = _sourceRange.Worksheet.Column(_sourceRange._fromCol + col + diff).OutlineLevel;
}
}

if (EnumUtil.HasFlag(_copyOptions, ExcelRangeCopyOptionFlags.IncludeFullRow))
if (EnumUtil.HasFlag(_copyOptions, ExcelRangeCopyOptionFlags.IncludeFullRow) && dimFromRow > 0)
{
var sourceRowOrig = _sourceRange._fromRow;
var destRowOrig = _destinationRange._fromRow;

for (int i = 0; i < _sourceRange.Rows; i++)
var diff = dimFromRow - _sourceRange._fromRow;
for (int i = 0; i < (dimToRow - dimFromRow + 1); i++)
{
var sourceRow = _sourceRange.Worksheet.Row(sourceRowOrig + i);
var destRow = _destinationRange.Worksheet.Row(destRowOrig + i);
var sourceRow = _sourceRange.Worksheet.Row(sourceRowOrig + i + diff);
var destRow = _destinationRange.Worksheet.Row(destRowOrig + i + diff);

destRow.Height = sourceRow.Height;
}
Expand All @@ -950,23 +954,27 @@ private void CopyFullRow()

private void CopyFullColumn()
{
_sourceRange.GetAddressDimensionFullRowAndColumn(out int dimFromRow, out int dimFromCol, out int dimToRow, out int dimToCol);
if (dimFromRow == 0 && dimFromCol == 0) return;
if (_sourceRange._fromCol == 1 && _sourceRange._toCol == ExcelPackage.MaxColumns)
{
for (int row = 0; row < _sourceRange.Rows; row++)
var diff = dimFromRow - _sourceRange._fromRow;
for (int row = 0; row < (dimToRow - dimFromRow + 1); row++)
{
_destinationRange.Worksheet.Row(_destinationRange.Start.Row + row).OutlineLevel = _sourceRange.Worksheet.Row(_sourceRange._fromRow + row).OutlineLevel;
_destinationRange.Worksheet.Row(_destinationRange.Start.Row + row + diff).OutlineLevel = _sourceRange.Worksheet.Row(_sourceRange._fromRow + row + diff).OutlineLevel;
}
}

if(EnumUtil.HasFlag(_copyOptions, ExcelRangeCopyOptionFlags.IncludeFullColumn))
if(EnumUtil.HasFlag(_copyOptions, ExcelRangeCopyOptionFlags.IncludeFullColumn) && dimFromCol > 0)
{
var destColOrig = _destinationRange._fromCol;
var sourceColOrig = _sourceRange._fromCol;

for (int i = 0; i < _sourceRange.Columns; i++)
var diff = dimFromCol - _sourceRange._fromCol;
for (int i = 0; i < (dimToCol - dimFromCol+1); i++)
{
var sourceCol = _sourceRange.Worksheet.Column(sourceColOrig + i);
var destCol = _destinationRange.Worksheet.Column(destColOrig + i);
var sourceCol = _sourceRange.Worksheet.Column(sourceColOrig + i + diff);
var destCol = _destinationRange.Worksheet.Column(destColOrig + i + diff);

destCol.Width = sourceCol.Width;
}
Expand Down
130 changes: 104 additions & 26 deletions src/EPPlus/Drawing/ExcelDrawing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ Date Author Change
using OfficeOpenXml.Drawing.OleObject;
using OfficeOpenXml.Drawing.Slicer;
using OfficeOpenXml.FormulaParsing.Excel.Functions.MathFunctions;
using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
using OfficeOpenXml.Packaging;
using OfficeOpenXml.Utils;
using OfficeOpenXml.Utils.Drawings;
using OfficeOpenXml.Utils.EnumUtils;
using OfficeOpenXml.Utils.FileUtils;
using OfficeOpenXml.Utils.XML;
Expand All @@ -25,6 +28,7 @@ Date Author Change
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Xml;

Expand Down Expand Up @@ -731,8 +735,8 @@ internal void GetFromBounds(out int fromRow, out int fromRowOff, out int fromCol
{
if (CellAnchor == eEditAs.Absolute)
{
GetToRowFromPixels(Position.Y, out fromRow, out fromRowOff);
GetToColumnFromPixels(Position.X, out fromCol, out fromColOff);
GetToRowFromPixels(Position.Y / (double)EMU_PER_PIXEL, out fromRow, out fromRowOff);
GetToColumnFromPixels(Position.X / (double)EMU_PER_PIXEL, out fromCol, out fromColOff);
}
else
{
Expand All @@ -747,7 +751,7 @@ internal void GetToBounds(out int toRow, out int toRowOff, out int toCol, out in
if (CellAnchor == eEditAs.Absolute)
{
GetToRowFromPixels((Position.Y + Size.Height) / EMU_PER_PIXEL, out toRow, out toRowOff);
GetToColumnFromPixels(Position.X + Size.Width / EMU_PER_PIXEL, out toCol, out toColOff);
GetToColumnFromPixels((Position.X + Size.Width) / EMU_PER_PIXEL, out toCol, out toColOff);
}
else
{
Expand Down Expand Up @@ -855,15 +859,14 @@ internal double GetPixelWidth()
if (CellAnchor == eEditAs.TwoCell)
{
ExcelWorksheet ws = _drawings.Worksheet;
double mdw = ws.Workbook.MaxFontWidth;

pix = -From.ColumnOff / (double)EMU_PER_PIXEL;
for (int col = From.Column + 1; col <= To.Column; col++)
{
pix += MathHelper.TruncateDouble(((256 * ws.GetColumnWidth(col) + MathHelper.TruncateDouble(128 / mdw)) / 256) * mdw);
pix += PixelHelper.GetColumnWidth(ws, col);
}

var w = MathHelper.TruncateDouble(((256 * ws.GetColumnWidth(To.Column + 1) + MathHelper.TruncateDouble(128 / mdw)) / 256) * mdw);
var w = PixelHelper.GetColumnWidth(ws, To.Column + 1);
pix += Math.Min(w, Convert.ToDouble(To.ColumnOff) / EMU_PER_PIXEL);
}
else
Expand Down Expand Up @@ -898,9 +901,9 @@ internal double GetPixelHeight()
pix = -(From.RowOff / (double)EMU_PER_PIXEL);
for (int row = From.Row + 1; row <= To.Row; row++)
{
pix += ws.GetRowHeight(row) / 0.75;
pix += PixelHelper.GetRowHeight(ws, row);
}
var h = ws.GetRowHeight(To.Row + 1) / 0.75;
var h = PixelHelper.GetRowHeight(ws, To.Row + 1);
pix += Math.Min(h, Convert.ToDouble(To.RowOff) / EMU_PER_PIXEL);
}
else
Expand Down Expand Up @@ -939,12 +942,12 @@ internal void CalcRowFromPixelTop(double pixels, out int row, out int rowOff)
ExcelWorksheet ws = _drawings.Worksheet;
double mdw = ws.Workbook.MaxFontWidth;
double prevPix = 0;
double pix = ws.GetRowHeight(1) / 0.75;
double pix = PixelHelper.GetRowHeight(ws, 1);
int r = 2;
while (pix < pixels)
while (pix < pixels && r <= ExcelPackage.MaxRows)
{
prevPix = pix;
pix += (int)(ws.GetRowHeight(r++) / 0.75);
pix += (int)PixelHelper.GetRowHeight(ws, r++);
}

if (pix == pixels)
Expand Down Expand Up @@ -987,15 +990,14 @@ internal void CalcColFromPixelLeft(double pixels, out int column, out int column
{

ExcelWorksheet ws = _drawings.Worksheet;
double mdw = ws.Workbook.MaxFontWidth;
double prevPix = 0;
double pix = (int)MathHelper.TruncateDouble(((256 * ws.GetColumnWidth(1) + MathHelper.TruncateDouble(128 / mdw)) / 256) * mdw);
double pix = (int)PixelHelper.GetColumnWidth(ws, 1);
int col = 2;

while (pix < pixels)
while (pix < pixels && col <= ExcelPackage.MaxColumns)
{
prevPix = pix;
pix += (int)MathHelper.TruncateDouble(((256 * ws.GetColumnWidth(col++) + MathHelper.TruncateDouble(128 / mdw)) / 256) * mdw);
pix += (int)PixelHelper.GetColumnWidth(ws, col++);
}
if (pix == pixels)
{
Expand Down Expand Up @@ -1033,20 +1035,40 @@ internal void SetPixelHeight(double pixels)

internal void GetToRowFromPixels(double pixels, out int toRow, out int rowOff, int fromRow = -1, int fromRowOff = -1)
{
if (From == null && this is not ExcelControl)
{
// Absolute anchor path
double remaining = pixels;
int currentRow = 1;

while (true && currentRow <= ExcelPackage.MaxRows)
{
double rowPix = PixelHelper.GetRowHeight(_drawings.Worksheet, currentRow);
if (remaining < rowPix)
break;

remaining -= rowPix;
currentRow++;
}

toRow = currentRow - 1;
rowOff = (int)(remaining);
return;
}
if (fromRow < 0)
{
fromRow = From.Row;
fromRowOff = From.RowOff;
}
ExcelWorksheet ws = _drawings.Worksheet;
var pixOff = pixels - ((ws.GetRowHeight(fromRow + 1) / 0.75) - (fromRowOff / (double)EMU_PER_PIXEL));
var pixOff = pixels - (PixelHelper.GetRowHeight(ws, fromRow + 1) - (fromRowOff / (double)EMU_PER_PIXEL));
double prevPixOff = pixels;
int row = fromRow + 1;

while (pixOff >= 0)
while (pixOff >= 0 && row < ExcelPackage.MaxRows)
{
prevPixOff = pixOff;
pixOff -= (ws.GetRowHeight(++row) / 0.75);
pixOff -= PixelHelper.GetRowHeight(ws, ++row);
}
toRow = row - 1;
if (fromRow == toRow)
Expand Down Expand Up @@ -1086,19 +1108,35 @@ internal void SetPixelWidth(double pixels)
internal void GetToColumnFromPixels(double pixels, out int col, out int colOff, int fromColumn = -1, int fromColumnOff = -1)
{
ExcelWorksheet ws = _drawings.Worksheet;
double mdw = ws.Workbook.MaxFontWidth;
if (fromColumn < 0)
if (From == null && this is not ExcelControl)
{
// Absolute anchor path
double remaining = pixels;
int currentCol = 1;
double colPix = PixelHelper.GetColumnWidth(ws, currentCol);
while (remaining >= colPix && currentCol < ExcelPackage.MaxColumns)
{
remaining -= colPix;
currentCol++;
colPix = PixelHelper.GetColumnWidth(ws, currentCol);
}

col = currentCol-1;
colOff = (int)(remaining);
return;
}
if (From != null && fromColumn < 0)
{
fromColumn = From.Column;
fromColumnOff = From.ColumnOff;
}
double pixOff = pixels - (MathHelper.TruncateDouble(((256 * ws.GetColumnWidth(fromColumn + 1) + MathHelper.TruncateDouble(128 / mdw)) / 256) * mdw) - fromColumnOff / EMU_PER_PIXEL);
double pixOff = pixels - (PixelHelper.GetColumnWidth(ws, fromColumn + 1) - fromColumnOff / EMU_PER_PIXEL);
double offset = (double)fromColumnOff / EMU_PER_PIXEL + pixels;
col = fromColumn + 2;
while (pixOff >= 0)
{
offset = pixOff;
pixOff -= MathHelper.TruncateDouble(((256 * ws.GetColumnWidth(col++) + MathHelper.TruncateDouble(128 / mdw)) / 256) * mdw);
pixOff -= PixelHelper.GetColumnWidth(ws, col++);
}
colOff = (int)offset;
}
Expand Down Expand Up @@ -1384,10 +1422,20 @@ public void SetPosition(int Row, int RowOffsetPixels, int Column, int ColumnOffs
_height = GetPixelHeight();
}

From.Row = Row;
From.RowOff = RowOffsetPixels * EMU_PER_PIXEL;
From.Column = Column;
From.ColumnOff = ColumnOffsetPixels * EMU_PER_PIXEL;
if (CellAnchor == eEditAs.Absolute)
{
GetPixelHeightFromRow(Row, RowOffsetPixels, out int pixelHeight);

Position.Y = (int)(pixelHeight * EMU_PER_PIXEL);
Position.X = (int)(ColumnOffsetPixels * EMU_PER_PIXEL);
}
else
{
From.Row = Row;
From.RowOff = RowOffsetPixels * EMU_PER_PIXEL;
From.Column = Column;
From.ColumnOff = ColumnOffsetPixels * EMU_PER_PIXEL;
}
if (CellAnchor == eEditAs.TwoCell)
{
_left = GetPixelLeft();
Expand All @@ -1399,6 +1447,36 @@ public void SetPosition(int Row, int RowOffsetPixels, int Column, int ColumnOffs
_doNotAdjust = false;
UpdatePositionAndSizeXml();
}
private void GetPixelWidthFromRow(int toCol, int colOffsetPixels, out int pixelWidth)
{
ExcelWorksheet ws = _drawings.Worksheet;
double mdw = ws.Workbook.MaxFontWidth;

pixelWidth = 0;
for (int col = 0; col < toCol; col++)
{
pixelWidth += ws.GetColumnWidthPixels(col, mdw);
}
pixelWidth += colOffsetPixels;
}
private void GetPixelHeightFromRow(int toRow, int rowOffsetPixels, out int pixelHeight)
{
pixelHeight = 0;
var cache = _drawings.Worksheet.RowHeightCache;
for (int row = 0; row < toRow; row++)
{
lock (cache)
{
if (!cache.ContainsKey(row))
{
cache.Add(row, _drawings.Worksheet.GetRowHeight(row + 1));
}
}
pixelHeight += (int)(cache[row] / 0.75);
}
pixelHeight += rowOffsetPixels;
}

/// <summary>
/// Set size in Percent.
/// Note that resizing columns / rows after using this function will effect the size of the drawing
Expand Down
1 change: 1 addition & 0 deletions src/EPPlus/ExcelPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,7 @@ private XmlNamespaceManager CreateDefaultNSM()
ns.AddNamespace("xda", schemaDynamicArrays);
ns.AddNamespace("clbl", schemaMipLabelMetadata);
ns.AddNamespace("xfpb", Schemas.schemaFeaturePropertyBag);
ns.AddNamespace("xcalcf", Schemas.schemaCalcFeature);
return ns;
}
#region SavePart
Expand Down
Loading
Loading