0x00. 场景
日常使用Excel表格过程中,经常会遇到需要在单元格内插入图片的情形,比如证件照、身份证正反面等情况。为了美观且便于查看,WPS提供了“图片嵌入单元格”功能,可谓非常好用。
我开发小工具时使用Golang语言居多,处理Excel表格使用的是Excelize开源库,Excelize提供了自动适应单元格选项AutoFit
(从字面意思看,似乎符合我们的需求),官方文档如下:
可选参数 AutoFit 用以指定是否使图形对象尺寸自动适合单元格,其默认值为 false。
通过翻看源码,AutoFit
参数优先按单元格高度缩放图片,若图片高度小于单元格高度,则按单元格宽度缩放图片。
// drawingResize calculate the height and width after resizing.
func (f *File) drawingResize(sheet, cell string, width, height float64, opts *GraphicOptions) (w, h, c, r int, err error) {
// 省略若干代码
if float64(cellWidth) < width {
asp := float64(cellWidth) / width
width, height = float64(cellWidth), height*asp
}
if float64(cellHeight) < height {
asp := float64(cellHeight) / height
height, width = float64(cellHeight), width*asp
}
// 省略若干代码
}
实际使用下来,只适应了宽或高,效果跟预期不一致。
0x01. 魔改
既然我们已经定位到计算图片宽度的参数了,那剩下的只需要将图片的宽高按单元格的尺寸进行缩放,就能达到填满单元格的效果了。
-
新增GraphicOptions.Fill参数
-
修改drawingResize方法实现
// drawingResize calculate the height and width after resizing. func (f *File) drawingResize(sheet, cell string, width, height float64, opts *GraphicOptions) (w, h, c, r int, err error) { // 省略若干代码 if opts.Fill { width, height = float64(cellWidth), float64(cellHeight) } else { if float64(cellWidth) < width { asp := float64(cellWidth) / width width, height = float64(cellWidth), height*asp } if float64(cellHeight) < height { asp := float64(cellHeight) / height height, width = float64(cellHeight), width*asp } width, height = width-float64(opts.OffsetX), height-float64(opts.OffsetY) } // 省略若干代码 }
-
经过测试,符合预期。
0x02. 后续
所谓“魔改”,就是直接强行修改Excelize本地包源码,不方便项目托管和开发,也不方便依赖库的版本升级。
那么最好的方式就是让官方支持这个特性,所以我向官方仓库提交了Support filling images in cells #1923,经过旭日大佬的修改,现已合并进主分支了。
在以后的Excelize版本中,就可以直接使用AutoFitIgnoreAspect
参数完成上述需求了。