Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel Epplus设置位置图片问题_Excel_C# 4.0_Epplus - Fatal编程技术网

Excel Epplus设置位置图片问题

Excel Epplus设置位置图片问题,excel,c#-4.0,epplus,Excel,C# 4.0,Epplus,我正在使用Asp.Net C#生成Excel 2010及以上兼容文件。 我使用的是目前最新的3.1.2版 我先设置行高,然后再添加以下图片: ExcelPackage pck = new ExcelPackage(); var ws = pck.Workbook.Worksheets.Add("sheet 1"); while (i < dt.Rows.Count + offset) { ws.Row(i).Height = 84; i++; } node.SelectS

我正在使用Asp.Net C#生成Excel 2010及以上兼容文件。 我使用的是目前最新的3.1.2版

我先设置行高,然后再添加以下图片:

ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("sheet 1");
while (i < dt.Rows.Count + offset)
{
    ws.Row(i).Height = 84;
    i++;
}
node.SelectSingleNode("xdr:to",NameSpaceManager);
这是可行的,但它不能:

var prodImg = ws.Drawings.AddPicture(dr["code"].ToString(), new FileInfo(path));
int w = prodImg.Image.Width;
int h = prodImg.Image.Height;

if (h > 140) // because height of 84 is 140 pixels in excel
{
    double scale = h / 140.0;
    w = (int)Math.Floor(w / scale);
    h = 140;
}

int xOff = (150 - w) / 2;
int yOff = (140 - h) / 2;

prodImg.SetPosition(i - 1, xOff, 11, yOff);
prodImg.SetSize(w, h);
这会导致图像偏心和未调整大小。这个代码在同一个循环中:

var prodImgDm = ws.Drawings.AddPicture("bcdm" + dr["code"].ToString(), new FileInfo(pathDm));
prodImgDm.SetPosition(i - 1, 25, 15, 40);
prodImgDm.SetSize(100);
这有时确实有效。图片
prodImgDm
是具有静态宽度和高度的datamatrix图像,不需要调整大小,因为它们总是很小/很小。因此,如果在某些行中没有
SetSize
,它也可以工作,而在其他一些行中,它不工作。真奇怪,因为代码是一样的。它可能在库和/或Excel中。也许我用错了?有epplus图片专家吗

提前谢谢

编辑有时候一张图片抵得上千言万语,所以这里是截图。正如您所看到的,产品图像在单元格中不是水平和垂直对齐的。最右边的datamatrix有时会缩放到120%,即使我设置了
SetSize(100)
,这对我来说真的很奇怪。所以最后一个数据矩阵的大小是正确的。。。我已经找到了,但我想这对我没有帮助

编辑2013/04/09 Essenpillai给了我一个设置的提示

pck.DoAdjustDrawings = false;
但这给了我更奇怪的印象:


datamatrix仍在按行更改。第二排可以,第二排不行。ean13代码太宽。

我对Epplus库也有同样的问题 在我的代码中找不到解决这个问题的方法后,我检查了这个库。 Epplus创建excel图片始终为
twoCellAnchor
绘图。在
xlsx
文件中,您可以使用以下代码找到
drawingXYZ.xml

<xdr:twoCellAnchor editAs="oneCell">
  <xdr:from> ... </xdr:from>
  <xdr:to> ... </xdr:to>
  <xdr:pic>
  ...
</xdr:twoCellAnchor>
您可以轻松创建自己的dll副本。好消息是,您只需修改两个文件即可解决此问题。所以

从Visual Studio下载并打开Epplus库的源代码副本

我们需要将
绘图
的代码生成为oneCellAnchor,因此我们必须删除图片的
元素,并创建以图片尺寸为参数的元素

新的xml结构如下所示:

<xdr:oneCellAnchor editAs="oneCell">
  <xdr:from> ... </xdr:from>
  <xdr:ext cx="1234567" cy="7654321" />
  <xdr:pic>
  ...
</xdr:oneCellAnchor>
然后,我们在同一个文件中修改了两种方法,用于
AddPicture

public ExcelPicture AddPicture(string Name, Image image, Uri Hyperlink)
{
  if (image != null) {
    if (_drawingNames.ContainsKey(Name.ToLower())) {
      throw new Exception("Name already exists in the drawings collection");
    }
    XmlElement drawNode = CreateDrawingXml(false);
    // Change: we need create element with dimensions
    // like: <xdr:ext cx="3857625" cy="1047750" />
    XmlElement xdrext = _drawingsXml.CreateElement(
      "xdr", "ext", ExcelPackage.schemaSheetDrawings);
    xdrext.SetAttribute("cx", 
      (image.Width * ExcelDrawing.EMU_PER_PIXEL).ToString());
    xdrext.SetAttribute("cy", 
      (image.Height * ExcelDrawing.EMU_PER_PIXEL).ToString());
    drawNode.AppendChild(xdrext);
    // End of change, next part of method is the same:
    drawNode.SetAttribute("editAs", "oneCell");
    ...
  }
}
所以,这些都是重要的代码。现在我们必须更改用于搜索节点的代码,并保持元素的顺序

private void AddDrawings()
中,我们将
xpath
更改为:

XmlNodeList list = _drawingsXml.SelectNodes(
  "//xdr:twoCellAnchor", NameSpaceManager);
对此

XmlNodeList list = _drawingsXml.SelectNodes(
  "//(xdr:twoCellAnchor or xdr:oneCellAnchor)", NameSpaceManager);
都在这个文件中,现在我们更改
ExcelPicture.cs()

用于在构造函数中追加下一个代码的原始代码查找节点,如下所示:

ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("sheet 1");
while (i < dt.Rows.Count + offset)
{
    ws.Row(i).Height = 84;
    i++;
}
node.SelectSingleNode("xdr:to",NameSpaceManager);
因为我们不总是创建
元素,所以我们更改此代码:

internal ExcelPicture(ExcelDrawings drawings, XmlNode node
  , Image image, Uri hyperlink) 
  : base(drawings, node, "xdr:pic/xdr:nvPicPr/xdr:cNvPr/@name")
{
  XmlElement picNode = node.OwnerDocument.CreateElement(
    "xdr", "pic", ExcelPackage.schemaSheetDrawings);
  // Edited: find xdr:to, or xdr:ext if xdr:to not exists
  XmlNode befor = node.SelectSingleNode("xdr:to",NameSpaceManager);
  if (befor != null && befor.Name == "xdr:to")
    node.InsertAfter(picNode, befor);
  else {
    befor = node.SelectSingleNode("xdr:ext", NameSpaceManager);
    node.InsertAfter(picNode, befor);
  }
  // End of change, next part of constructor is unchanged
  _hyperlink = hyperlink;
  ...
}
输入参数为FileInfo的第二个构造函数也是如此:

public ExcelPicture AddPicture(string Name, FileInfo ImageFile, Uri Hyperlink)
{
  if (ImageFile != null) {
    if (_drawingNames.ContainsKey(Name.ToLower())) {
      throw new Exception("Name already exists in the drawings collection");
    }
    XmlElement drawNode = CreateDrawingXml(false);
    // Change: First create ExcelPicture object and calculate EMU dimensions
    ExcelPicture pic = new ExcelPicture(this, drawNode, ImageFile, Hyperlink);
    XmlElement xdrext = _drawingsXml.CreateElement(
      "xdr", "ext", ExcelPackage.schemaSheetDrawings);
    xdrext.SetAttribute("cx", 
      (pic.Image.Width * ExcelDrawing.EMU_PER_PIXEL).ToString());
    xdrext.SetAttribute("cy", 
      (pic.Image.Height * ExcelDrawing.EMU_PER_PIXEL).ToString());
    drawNode.AppendChild(xdrext);
    // End of change, next part of method is the same (without create pic object)
    drawNode.SetAttribute("editAs", "oneCell");
    ...
  }
}
internal ExcelPicture(ExcelDrawings drawings, XmlNode node
  , FileInfo imageFile, Uri hyperlink) 
  : base(drawings, node, "xdr:pic/xdr:nvPicPr/xdr:cNvPr/@name")
{
  XmlElement picNode = node.OwnerDocument.CreateElement(
    "xdr", "pic", ExcelPackage.schemaSheetDrawings);
  // Edited: find xdr:to, or xdr:ext if xdr:to not exists
  XmlNode befor = node.SelectSingleNode("xdr:to", NameSpaceManager);
  if (befor != null && befor.Name == "xdr:to")
    node.InsertAfter(picNode, befor);
  else {
    befor = node.SelectSingleNode("xdr:ext", NameSpaceManager);
    node.InsertAfter(picNode, befor);
  }
  // End of change, next part of constructor is unchanged
  _hyperlink = hyperlink;
  ...
现在,图片被创建为
oneCellAnchor
。如果需要,您可以为展位变体创建多个
AddPicture
方法。最后一步是构建此项目并创建自己的自定义
EPPlus.dll
。然后关闭使用此dll的项目,并在同一位置复制项目中的新文件
EPPlus.dll
EPPlus.pdb
EPPlus.XML
(备份并替换原始dll文件)(因此您不需要对项目引用或设置进行任何更改)。

然后打开并重建您的项目,并尝试解决您的问题。

也许我太迟了,但这是我的答案。。 您也可以在codeplex问题上阅读它 ()


我也有这个问题

经过一些研究,我找到了错误所在

它位于代码行(ExcelRow.cs文件)上的ExcelRow类中

有一个错误,当行的高度被更改时,它会重新计算所有图片的高度,但使用图片宽度代替高度,所以很容易修复

换线就行了

var pos = _worksheet.Drawings.GetDrawingWidths();

版本4.0.4的p.S.实际值


看起来对该项目来说是一个很好的拉动请求。另外,我找到了这个资源,它建议图纸应该有editas道具集。在那里你可以选择绝对,一个单元格,两个单元格这是我们用艾普拉斯控件封装的一个插入图片的方法,希望对你有帮助。虽然这个代码片段可能是解决方案,但它确实有助于提高文章的质量。请记住,您将在将来回答读者的问题,这些人可能不知道您的代码建议的原因。太好了。为我工作。谢谢:)对不起,我的英语太差了,说不了多少英语
var pos = _worksheet.Drawings.GetDrawingWidths();
var pos = _worksheet.Drawings.GetDrawingHeight();
public static void CreatePicture(ExcelWorksheet worksheet, string name, Image image, int firstColumn, int lastColumn, int firstRow, int lastRow, int defaultOffsetPixels)
        {
            int columnWidth = GetWidthInPixels(worksheet.Cells[firstRow, firstColumn]);
            int rowHeight = GetHeightInPixels(worksheet.Cells[firstRow, firstColumn]);

            int totalColumnWidth = columnWidth * (lastColumn - firstColumn + 1);
            int totalRowHeight = rowHeight * (lastRow - firstRow + 1);
            double cellAspectRatio = Convert.ToDouble(totalColumnWidth) / Convert.ToDouble(totalRowHeight);

            int imageWidth = image.Width;
            int imageHeight = image.Height;
            double imageAspectRatio = Convert.ToDouble(imageWidth) / Convert.ToDouble(imageHeight);

            int pixelWidth;
            int pixelHeight;
            if (imageAspectRatio > cellAspectRatio)
            {
                pixelWidth = totalColumnWidth - defaultOffsetPixels * 2;
                pixelHeight = pixelWidth * imageHeight / imageWidth;
            }
            else
            {
                pixelHeight = totalRowHeight - defaultOffsetPixels * 2;
                pixelWidth = pixelHeight * imageWidth / imageHeight;
            }

            int rowOffsetPixels = (totalRowHeight - pixelHeight) / 2;
            int columnOffsetPixels = (totalColumnWidth - pixelWidth) / 2;

            int rowOffsetCount = 0;
            int columnOffsetCount = 0;

            if (rowOffsetPixels > rowHeight)
            {
                rowOffsetCount = (int)Math.Floor(Convert.ToDouble(rowOffsetPixels) / Convert.ToDouble(rowHeight));
                rowOffsetPixels -= rowHeight * rowOffsetCount;
            }

            if (columnOffsetPixels > columnWidth)
            {
                columnOffsetCount = (int)Math.Floor(Convert.ToDouble(columnOffsetPixels) / Convert.ToDouble(columnWidth));
                columnOffsetPixels -= columnWidth * columnOffsetCount;
            }

            int row = firstRow + rowOffsetCount - 1;
            int column = firstColumn + columnOffsetCount - 1;

            ExcelPicture pic = worksheet.Drawings.AddPicture(name, image);
            pic.SetPosition(row, rowOffsetPixels, column, columnOffsetPixels);
            pic.SetSize(pixelWidth, pixelHeight);
        }

        public static int GetHeightInPixels(ExcelRange cell)
        {
            using (Graphics graphics = Graphics.FromHwnd(IntPtr.Zero))
            {
                float dpiY = graphics.DpiY;
                return (int)(cell.Worksheet.Row(cell.Start.Row).Height * (1 / 72.0) * dpiY);
            }
        }

        public static float MeasureString(string s, Font font)
        {
            using (var g = Graphics.FromHwnd(IntPtr.Zero))
            {
                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                return g.MeasureString(s, font, int.MaxValue, StringFormat.GenericTypographic).Width;
            }
        }

        public static int GetWidthInPixels(ExcelRange cell)
        {
            double columnWidth = cell.Worksheet.Column(cell.Start.Column).Width;
            Font font = new Font(cell.Style.Font.Name, cell.Style.Font.Size, FontStyle.Regular);
            double pxBaseline = Math.Round(MeasureString("1234567890", font) / 10);
            return (int)(columnWidth * pxBaseline);
        }