从Excel中导出图片,是一个很常规的需求,也有一些久旧不衰的界面操作法小技巧从OpenXml文件中批量导出,在VBA开发中,也会使用Chart对象的背景图的技巧来导出。总体来说,和真正想要的效果还是有差距,特别是这样的方式导出的图片像素会低。 在VSTO开发中,有更好的方式,此篇给大家一一分享。
使用Excel催化剂的插入图片的方式,图片已经存储在PictureBox容器内,想导出时,只需在PictureBox容器上取出其Image属性,即可拿到图片,再简单的一个保存为文件的方法即可完成。
以下为Excel催化剂的批量导出图片功能的代码。核心代码就几句完成,可见用PictureBox容器装载图片的优势非常明显。
public static void OutputMultiPic()
{
foreach (Excel.ListRow row in listObjectOfImageInfo.ListRows)
{
Excel.Range shpNameRange = row.Range.Cells[listObjectOfImageInfo.ListColumns["图形名称"].Index];
Excel.Range filePathRange = row.Range.Cells[listObjectOfImageInfo.ListColumns["导出文件名全路径"].Index];
if (row.Range.Height>0 && shpNameRange.Value2!=null && filePathRange.Value2!=null)
{
string filePath = filePathRange.Value2.ToString();
string shpName = shpNameRange.Value2.ToString();
Image image = listImageInfo.FirstOrDefault(s => s.ShapeName == shpName).ImageFile;
image.Save(filePath);
}
}
}
在非PictureBox容器装载的图片,其实也可以用间接的方式实现,将普通的图片或图表等对形状对象,转换为Image类型的图片,并且可以保证到图片大小是最原始的图片。
原理是使用剪切板将图片复制到内存剪切板中,再由剪切板转换为图片,在复制过程中,我们需要考虑原始的图片在Excel上显示是已经缩放过的,需要将其放大为原始尺寸再复制。具体代码如下:
public static Image GetImageFromShape(Excel.Shape shp)
{
Excel.Shape shape = shp.Duplicate();
shape.LockAspectRatio = Microsoft.Office.Core.MsoTriState.msoTrue;
if (shp.Type.ToString() == "msoPicture")
{
shape.ScaleHeight(1, Microsoft.Office.Core.MsoTriState.msoTrue, Microsoft.Office.Core.MsoScaleFrom.msoScaleFromTopLeft);
}
else
{
shape.ScaleHeight(1, Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoScaleFrom.msoScaleFromTopLeft);
}
shape.Copy();
shape.Delete();
Image returnImage = null;
if (Clipboard.ContainsImage())
{
returnImage = Clipboard.GetImage();
}
return returnImage;
}
核心代码中shape.ScaleHeight方法,可以将图片放大,特别是图形Shape类型时,可以按原始图来放大,其他的按实际显示的大小来放大。
同样地放大之前先锁定纵横比shape.LockAspectRatio,使用此属性。
结语
此篇再次让大家见识了VSTO开发较VBA开发的一大优势,有大量的.Net下的Winform技术可供使用,像剪切板对象,其就是System.Windows.Forms命名空间下的类。直接大量的现成方法简单调用,无需像VBA那般苦苦地挣扎着,调用各种古老方法或系统API等来扩展原生VBA对象的不足。
同时VSTO框架下,大量的特有功能,如PictureBox窗体宿主控件等可以大大地丰富了原生Excel的功能,也是VBA开发所不能享受到的好处。