我可以将图像设置为 *不* 自动调整大小吗?

3
我有一个“模板”Excel文件,其中设置了一些基本的布局(一些合并单元格,一些列宽等),然后使用ClosedXML填充数据。基本上,它很简单:
var workbook = new XLWorkbook(filePath);
workbook.Worksheets.Single().Cell(1, 4).Value = someTextValue;
workbook.Worksheets.Single().Cell(1, 4).Style.Alignment.WrapText = true;
// set other values, etc.

整个过程涉及将文件复制到另一个流中,从Web应用程序返回它进行下载等操作。
静态模板文件中的其中一个单元格具有图像。该行上的另一个单元格需要自动展开以适应换行文本和回车符。设置上面的WrapText属性时,行的自动展开效果很好。然而,图片也会扩展其高度(因此变得明显失真)。
在文件本身中,我右键单击图像以设置其格式,在“大小和属性”下,我明确选择了“不随单元格移动或缩放”。但是,通过ClosedXML交互自动调整行仍然会导致图像调整大小。
我尝试过的另一件事是以某种方式将图像与行“分离”,方法是将其放入文本框中。但是,似乎图像和文本框同样“浮动”在单元格上,而图像无法放置在文本框中(或者我不知道如何操作)。
看起来ClosedXML对图像没有太多支持(除非我看错了)。在这种设置中,是否有任何方法可以防止此图像随行自动调整大小?

你能找到解决方案吗?像你一样,我也想保持这个非开发人员友好。 - clinch
1
@clinch:最终我不得不采用以下解决方案。如果有其他方法,我从未发现过。我基本上创建了一个控制台应用程序,它将接受用户制作的 Excel 模板(其中已知内容很少能被用户编辑),并处理一次以生成主应用程序可以使用的版本。 - David
1个回答

3
我曾经遇到过类似的问题,我的解决方法是使用绝对定位锚点来放置图片,在Excel中本身无法完成这一操作,原因不详...
我编写了一个控制台应用程序,使用OpenXML SDK生成模板Excel文件,代码类似于这里的代码。锚点的代码如下:
Position pos = new Position();
pos.X = 0;
pos.Y = 0;
Extent ext = new Extent();
ext.Cx = extents.Cx;
ext.Cy = extents.Cy;
AbsoluteAnchor anchor = new AbsoluteAnchor();
anchor.Position = pos;
anchor.Extent = ext;
anchor.Append(picture);
anchor.Append(new ClientData());

在紧急情况下隐藏完整代码的代码片段:

static void Main(string[] args)
{
 string sFile = "ExcelOpenXmlWithImage.xlsx";
 if (File.Exists(sFile))
 {
  File.Delete(sFile);
 }
 BuildWorkbook(sFile);
}

private static void BuildWorkbook(string filename)
{
 try
 {
  using (SpreadsheetDocument xl = SpreadsheetDocument.Create(filename, SpreadsheetDocumentType.Workbook))
  {
   WorkbookPart wbp = xl.AddWorkbookPart();
   WorksheetPart wsp = wbp.AddNewPart<WorksheetPart>();
   Workbook wb = new Workbook();
   FileVersion fv = new FileVersion();
   fv.ApplicationName = "Microsoft Office Excel";
   Worksheet ws = new Worksheet();
   SheetData sd = new SheetData();

   string sImagePath = "polymathlogo.png";
   DrawingsPart dp = wsp.AddNewPart<DrawingsPart>();
   ImagePart imgp = dp.AddImagePart(ImagePartType.Png, wsp.GetIdOfPart(dp));
   using (FileStream fs = new FileStream(sImagePath, FileMode.Open))
   {
    imgp.FeedData(fs);
   }

   NonVisualDrawingProperties nvdp = new NonVisualDrawingProperties();
   nvdp.Id = 1025;
   nvdp.Name = "Picture 1";
   nvdp.Description = "polymathlogo";
   DocumentFormat.OpenXml.Drawing.PictureLocks picLocks = new DocumentFormat.OpenXml.Drawing.PictureLocks();
   picLocks.NoChangeAspect = true;
   picLocks.NoChangeArrowheads = true;
   NonVisualPictureDrawingProperties nvpdp = new NonVisualPictureDrawingProperties();
   nvpdp.PictureLocks = picLocks;
   NonVisualPictureProperties nvpp = new NonVisualPictureProperties();
   nvpp.NonVisualDrawingProperties = nvdp;
   nvpp.NonVisualPictureDrawingProperties = nvpdp;

   DocumentFormat.OpenXml.Drawing.Stretch stretch = new DocumentFormat.OpenXml.Drawing.Stretch();
   stretch.FillRectangle = new DocumentFormat.OpenXml.Drawing.FillRectangle();

   BlipFill blipFill = new BlipFill();
   DocumentFormat.OpenXml.Drawing.Blip blip = new DocumentFormat.OpenXml.Drawing.Blip();
   blip.Embed = dp.GetIdOfPart(imgp);
   blip.CompressionState = DocumentFormat.OpenXml.Drawing.BlipCompressionValues.Print;
   blipFill.Blip = blip;
   blipFill.SourceRectangle = new DocumentFormat.OpenXml.Drawing.SourceRectangle();
   blipFill.Append(stretch);

   DocumentFormat.OpenXml.Drawing.Transform2D t2d = new DocumentFormat.OpenXml.Drawing.Transform2D();
   DocumentFormat.OpenXml.Drawing.Offset offset = new DocumentFormat.OpenXml.Drawing.Offset();
   offset.X = 0;
   offset.Y = 0;
   t2d.Offset = offset;
   Bitmap bm = new Bitmap(sImagePath);
   //http://en.wikipedia.org/wiki/English_Metric_Unit#DrawingML
   //https://dev59.com/oHM_5IYBdhLWcg3whznx
   //https://dev59.com/Y3VC5IYBdhLWcg3w7V_3
   DocumentFormat.OpenXml.Drawing.Extents extents = new DocumentFormat.OpenXml.Drawing.Extents();
   extents.Cx = (long)bm.Width * (long)((float)914400 / bm.HorizontalResolution);
   extents.Cy = (long)bm.Height * (long)((float)914400 / bm.VerticalResolution);
   bm.Dispose();
   t2d.Extents = extents;
   ShapeProperties sp = new ShapeProperties();
   sp.BlackWhiteMode = DocumentFormat.OpenXml.Drawing.BlackWhiteModeValues.Auto;
   sp.Transform2D = t2d;
   DocumentFormat.OpenXml.Drawing.PresetGeometry prstGeom = new DocumentFormat.OpenXml.Drawing.PresetGeometry();
   prstGeom.Preset = DocumentFormat.OpenXml.Drawing.ShapeTypeValues.Rectangle;
   prstGeom.AdjustValueList = new DocumentFormat.OpenXml.Drawing.AdjustValueList();
   sp.Append(prstGeom);
   sp.Append(new DocumentFormat.OpenXml.Drawing.NoFill());

   DocumentFormat.OpenXml.Drawing.Spreadsheet.Picture picture = new DocumentFormat.OpenXml.Drawing.Spreadsheet.Picture();
   picture.NonVisualPictureProperties = nvpp;
   picture.BlipFill = blipFill;
   picture.ShapeProperties = sp;

   Position pos = new Position();
   pos.X = 0;
   pos.Y = 0;
   Extent ext = new Extent();
   ext.Cx = extents.Cx;
   ext.Cy = extents.Cy;
   AbsoluteAnchor anchor = new AbsoluteAnchor();
   anchor.Position = pos;
   anchor.Extent = ext;
   anchor.Append(picture);
   anchor.Append(new ClientData());
   WorksheetDrawing wsd = new WorksheetDrawing();
   wsd.Append(anchor);
   Drawing drawing = new Drawing();
   drawing.Id = dp.GetIdOfPart(imgp);

   wsd.Save(dp);

   ws.Append(sd);
   ws.Append(drawing);
   wsp.Worksheet = ws;
   wsp.Worksheet.Save();
   Sheets sheets = new Sheets();
   Sheet sheet = new Sheet();
   sheet.Name = "Sheet1";
   sheet.SheetId = 1;
   sheet.Id = wbp.GetIdOfPart(wsp);
   sheets.Append(sheet);
   wb.Append(fv);
   wb.Append(sheets);

   xl.WorkbookPart.Workbook = wb;
   xl.WorkbookPart.Workbook.Save();
   xl.Close();
  }
 }
 catch (Exception e)
 {
  Console.WriteLine(e.ToString());
  Console.ReadLine();
 }
}


这看起来真的很有用。可能要过一天左右,我才有机会真正地玩弄它,但它非常有帮助。它可能不能长期解决我的需求,因为非技术人员可能想要修改这些Excel模板,但我会测试一下,无论如何,这部分超出了问题的范围。这很棒,谢谢! - David

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接