C# 解决 Excel 自动适应列宽的问题

目录

问题现象

原因分析

范例运行环境

解决问题

生成测试文本

实现自适应

小结


问题现象

通过 COM 操作 Excel 自动适应列宽的方法是 AutoFit 方法,该方法适于自动适应列宽或行高。

最近在我们的一款应用里发现效果并没有符合预期,我们提供了一个可以设置导出Excel花名册的配置功能,如下图:

通过查询配置表,可以看到当选择需要输出的列的时候,可以设置 excel 列的宽度,以满足输出样式。列宽的值可以设置0到255的数值,在 C# 中列宽(ColumnWidth)是一个 dynamic 类型,如下示例代码:

cs 复制代码
Range  _range=excel.Range[excel.Cells[1,1],excel.Cells[65536,1]];

_range.ColumnWidth=255;

通过获取 Range 对象,将其 ColumnWidth 设置为我们配置的值。在我们的应用里,如果配置为 -1 ,则表示使用自动适应列宽模式,这就用到了如下代码:

cs 复制代码
Range  _range=excel.Range[excel.Cells[1,1],excel.Cells[65536,1]];

if(config_width==-1){
    _range.Columns.AutoFit();
}

我们在应用里配置了类似"家庭成员情况"、"主要社会关系人" 、"学习经历"、"工作经历" 等履历型的多行文本输出,使用了自动适应列宽模式,输出效果如下:

实际上是我们想要得到这样的效果:

原因分析

根据输出效果,我们在 Excel 里模拟操作一下自适应列宽,将鼠标移动到指定的列的表头的分隔线处,鼠标形状会显示为左右箭头分隔状,然后双击即可实现自动列宽。

发现有以下几种情况:

(1)如果单元格未设置为自动换行,我们将列宽手动调小于文字显示的长度,双击后将成功自动适应为最大文字长度的合适列宽。

(2)如果单元格设置为自动换行,我们将列宽手动调小于文字显示的长度,双击后将没有达成预期的显示列宽。

(3)如果单元格设置为自动换行,我们将列宽手动调大于多行文字显示的长度,双击后将成功自动适应为最大文字长度的合适列宽。

因此我们可以使用 C# 模拟情况(3)的操作来解决情况(2)的问题。

范例运行环境

操作系统: Windows Server 2019 DataCenter

.net版本: .netFramework4.0 或以上

Office Excel 2016

开发工具:VS2019 C#

解决问题

生成测试文本

我们假设生成了如下 HtmlTable 表格内容:

|-----|-------|------|----------|----|
| 姓名 | 与本人关系 | 政治面目 | 工作单位 | 职务 |
| 姓名1 | 父亲 | 群众 | 工作单位工作单位 | 工人 |
| 姓名2 | 母亲 | 群众 | 工作单位2 | 员工 |
| 姓名3 | 子女 | 群众 | 无工作单位 | 无 |

我们通过遍历行列的方法,计算每个单元格相对于列的最大字节数 GetByteCount(不是长度Length),示例代码如下:

cs 复制代码
            for (int i = 0; i < mtable.Rows[0].Cells.Count; i++)
            {
                int maxlen = 0;
                for (int j = 0; j < mtable.Rows.Count; j++)
                {
                    HtmlTableCell curcell=mtable.Rows[j].Cells[i];
                    int curlen=System.Text.Encoding.Default.GetByteCount(curcell.InnerText);
                    if (curlen > maxlen)
                    {
                        maxlen = curlen;
                    }
                }
                mtable.Rows[0].Cells[i].Attributes["maxlen"] = maxlen.ToString();
            }
            string excel = "";
            for (int i = 0; i < mtable.Rows.Count; i++)
            {
                for (int j = 0; j < mtable.Rows[i].Cells.Count; j++)
                {
                    int maxlen =int.Parse(mtable.Rows[0].Cells[j].Attributes["maxlen"]);
                    HtmlTableCell curcell = mtable.Rows[i].Cells[j];
                    excel += curcell.InnerText + string.Concat(Enumerable.Repeat(" ", maxlen - System.Text.Encoding.Default.GetByteCount(curcell.InnerText)))+"  " ;
curcell.InnerText);
                }
                excel += "\r\n";
            }

实现自适应

通过生成测试文本,保存到数据库并输出到 Excel 指定列,实现自适应非常简单,将列值设置为最大值,再使用自适应AutoFit 方法,即可以让 Excel 自动计算并重新调整列宽,代码如下:

cs 复制代码
Range  _range=excel.Range[excel.Cells[1,1],excel.Cells[65536,1]];

if(config_width==-1){
   _range.ColumnWidth = 255;
   _range.Columns.AutoFit();
}

自此完美解决。

小结

关于 AutoFit 方法的更多参考,请访问如下链接:

https://learn.microsoft.com/zh-cn/office/vba/api/excel.autofit?source=recommendations

本文代码仅供您参考使用,感谢您的阅读,希望本文能够对您有所帮助。

相关推荐
环能jvav大师几秒前
基于R语言的统计分析基础:使用SQL语句操作数据集
开发语言·数据库·sql·数据分析·r语言·sqlite
吱吱鼠叔3 分钟前
MATLAB方程求解:1.线性方程组
开发语言·matlab·php
Antonio9158 分钟前
【CMake】使用CMake在Visual Studio内构建多文件夹工程
开发语言·c++·visual studio
骆晨学长20 分钟前
基于springboot的智慧社区微信小程序
java·数据库·spring boot·后端·微信小程序·小程序
LyaJpunov22 分钟前
C++中move和forword的区别
开发语言·c++
AskHarries25 分钟前
利用反射实现动态代理
java·后端·reflect
程序猿练习生27 分钟前
C++速通LeetCode中等第9题-合并区间
开发语言·c++·leetcode
一名路过的小码农37 分钟前
C/C++动态库函数导出 windows
c语言·开发语言·c++
m0_6312704039 分钟前
标准c语言(一)
c语言·开发语言·算法
万河归海42839 分钟前
C语言——二分法搜索数组中特定元素并返回下标
c语言·开发语言·数据结构·经验分享·笔记·算法·visualstudio