笔者所在的项目,把Excel当作PPT来用,直接自动化将Excel内容转换为PPT,为了让PPT的表达观点能力得到体现,高频使用了文本框对象,堪称把文本框用到极致化。
文本框是形状的一个继承,有形状的所有功能,例如跟随单元格位置、大小这个常用的属性。
细心可看到它还有是否需要被打印,是否需要锁定它,锁定的颗粒度是全部锁定还是只锁定大小位置但开放文本编辑功能。
在笔者项目里,充分利用了这里锁定大小位置,不锁定文本的功能,让工作表处于保护状态,但仍开放给用户在文本框里填写内容的能力。实际场景是数据是从系统里导出引用过来的,不容许改变,但数据分析部分,开放给用户去填写。
除了基本的形状功能外,我们看到,它还有一个自己的分类叫文本框的属性(当然其他形状也有,因为可以在形状如矩形上写文字,效果就像矩形内部嵌入了一个文本框)。
这里有一些更细颗粒度的控制,例如根据文字调整形状大小,允许文本溢出形状等,这些效果会改变形状的大小,或文字超过形状范围外,在笔者当下的项目场景里是不允许的。但形状自动换行是需要的。让文字内容不会超过外围的框线位置。因为需要将它转到PDF,超越打印区域的内容变得无效,所以必须禁止。
文本框的文字排版内容,堪称半个WORD的世界,除了常规的字体、字号、加粗等设置外,还可以分栏,有段落、制表符、项目符号等。当然会比起WORD的排版还是弱了许多的,操作也没有WORD那么方便。
关于打印或转PDF时文本框信息会丢失问题,前一篇文章已经讲解了使用链接图片的技巧,生成一个emf矢量图片再打印或转PDF就可保留所有内容,这里不展开说明了。
『代码实现版续篇』彻底攻克Excel打印或转PDF信息丢失问题,附上攻克全过程
彻底攻克Excel打印或转PDF信息丢失问题,附上攻克全过程
当文字超过了文本框的下边框线时,这部分的文字在非编辑状态下会显示不出来。
在笔者项目里,需要保姆级别地发现这些未显示的内容,并告之用户,让用户自查并调整(缩小字体或拉大文本框高宽)。如何能够做到?经过反复研究,终于攻破了,真的差一点功力都失败了。
解决思路:比较文本框的高度和文字所在区域的高度,若文本框的高度比文字高度要小,就存在文字被遮挡显示不全的风险。
如何能够做到?
文本框有Height属性?文字区域有Height属性吗?还真有,chatgpt能够得到相应答案,然而事实远非这么简单。在Shae形状下面的TextFrame2对象里的TextRange对象,就是文字部分的对象,有外围高度值BoundHeight属性。
整个形状的高度,和文字的高度比较,还需要考虑到其上下边矩的问题,
计算公式应该为形状高度-上边矩-下边矩=文字区域高度。
到这里为止,看起来已经真相大白了,可以用上面的逻辑计算判断出有没遮挡的检验逻辑了。
然而这个逻辑成立的前提是,文本框的文字是非常正常地书写的。如果我的文字后面,多出一些回车换行符后,很崩溃,比较出来的结果是文字区域超了,提醒用户回来检查,用户检查发现明明没超,误报了,然后就没有然后了。
柳暗花明,发现TextRange2对象还有一个TrimText方法,可以去除文字的空格换行字符,更可喜的是它很人性地只去掉末尾的空格换行,在开头的就不去掉,仿佛这个方法,就是专门为这个比较有没有越界而生的一般。
这一次,有了这一系列的探索,答案已出来了,给出笔者在项目里判断的代码:
//批注文本框内容的高度和批注文本框高度比较,需要剔除上下边缘的留边大小,使用TrimText方法,可以得到清除末尾空格回车字符,不清除头部,实现了忽略末尾多余的空白字符。
if (txtBox.Height - txtBox.TextFrame2.MarginTop - txtBox.TextFrame2.MarginBottom < txtBox.TextFrame2.TextRange.TrimText().BoundHeight)
{
var txtBoxRange = sht.Range[txtBox.TopLeftCell, txtBox.BottomRightCell];
listErrors.Add($"工作表:{sht.Name},文本框位置:{txtBoxRange.Address[false, false]}");
}
本篇只是很粗略地探讨了一下Excel乃至OFFICE环境里的文本框的作用,真的是细节满满,OFFICE软件的更多研究,越发地感到深不见底,大量的细节在里面等待着挖掘。就如音乐世界里的古典音乐那般精彩,虽然在日常快餐文化世界中,可能不被发现,但其长尾功能,在特定场景上,真的非常贴心周到。希望本文的分享,能够给大家带来一些启发和新知。