C# 实现二维数据数组导出到 Excel

news2024/9/25 19:22:42

目录

功能需求

范例运行环境

Excel DCOM 配置

设计实现

组件库引入

​编辑​

方法设计

生成二维数据数组

核心方法实现

调用示例

总结


 

 

功能需求

将数据库查询出来的数据导出并生成 Excel 文件,是项目中经常使用的一项功能。本文将介绍通过数据集生成二维数据数组并导出到 Excel。

主要实现如下功能:

1、根据规则设计EXCEL数据导出模板

2、查询数据,并生成 object[,] 二维数据数组

3、将二维数据数组,其它要输出的数据导出写入到模板 Excel 文件

 

范例运行环境

操作系统: Windows Server 2019 DataCenter

操作系统上安装 Office Excel 2016

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

开发工具:VS2019  C#

Excel DCOM 配置

请参考我的文章《C# 读取Word表格到DataSet》有对Office DCOM详细配置介绍,这里不再赘述,Excel的对应配置名称如下图所示:

1072f229d76a5715dcb6542d89b41c06.png

  

设计实现

组件库引入

796f3a082e903b296b62ca33d4d5dcd8.png

方法设计

设计  expExcel 方法实现数据的导出,方法返回生成的全文件路径信息。其调用参数据详细说明见下表: 

序号参数名类型说明
1_filenamestringExcel 模板文件的全路径信息
2dataobjobject[,]生成的二维数据数组
3ActiveSheetIdint指定要导出的活动的SHEETID,序号从1开始
4StartRowIdint指定数据导出的开始行ID,序号从1开始
5StartColIdint指定数据导出的开始列ID,序号从1开始
6_replsstring[,]

在EXCEL模板文件里的查找且替换数组,维度1为 key ,维度2 为 value ,系统会根据提供的数组key在模板文件进行查找,并替换对应的 value 值,例如:

string[,] _repls=new string[1,2];

_repls[0,0]="模板标题 key "; 

_repls[0,1]="实际输出的标题值 value";

7drawtypeint

该值包括0和1。

0:从原始指定起始位置覆盖粘贴数据

1:从原始指定起始位置插入粘贴数据

8AllDataAsStringbool默认为 false,是否将所有数据以文本的形式进行输出
9DynamicColsbool默认为false,是否按照二维数据数组动态输出行与列
10DynamicColCfgArrayList

一个对各列进行配置的参数,每个项至少为两个object(一个为列名,一个为列宽),第三个为数据格式(如文本、数值等),例如:

ArrayList cfg = new ArrayList();

string _cname = "列名1";
string _width = "-1";   //-1 表示自动适应列宽
cfg.Add(new object[] { _cname, _width });

11StartAddressstring对 StartRowId 参数和 StartColId 参数

生成二维数据数组

如何生成二维数据数组,请参阅我的文章《C# 读取二维数组集合输出到Word预设表格》中的DataSet转二维数组 章节部分。

核心方法实现

代码如下:

public string expExcel(string _filename,object[,] dataobj,int ActiveSheetId,int StartRowId,int StartColId,string[,] _repls,int drawtype,bool AllDataAsString,bool DynamicCols,ArrayList DynamicColCfg,string StartAddress)
		{
			string AsString=(AllDataAsString?"'":"");
			string _file="",_path=Path.GetDirectoryName(_filename)+"\\tempbfile\\",_ext="";
			if(!Directory.Exists(_path))
			{
				Directory.CreateDirectory(_path);
			}

			_file=Path.GetFileNameWithoutExtension(_filename);
			_ext=Path.GetExtension(_filename);
			
			string _lastfile=_path+System.Guid.NewGuid()+_ext;
			File.Copy(_filename,_lastfile,true);
			if(!File.Exists(_lastfile))
			{
				return "";
			}
			//取得Word文件保存路径
			object filename=_lastfile;
			//创建一个名为ExcelApp的组件对象
			DateTime beforetime=DateTime.Now;
			Excel.Application excel=new Excel.Application();
			
            
			excel.DisplayAlerts=false;
			excel.AskToUpdateLinks=false;

			excel.Visible=true;
			
			DateTime aftertime=DateTime.Now;


			Excel.Workbook xb=excel.Workbooks.Add(_lastfile);
            
			Worksheet worksheet = (Worksheet) excel.Worksheets[ActiveSheetId];
			sheetCount=excel.Sheets.Count;
			worksheet.Activate();
            
			if(_repls!=null)
			{
				for(int i=0;i<_repls.GetLength(0);i++)
				{
					worksheet.Cells.Replace(_repls[i,0],_repls[i,1],Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing); 
				}
			}

			Excel.Range _range;
			Excel.Range srange;
			if(StartAddress!="")
			{
				Excel.Range _range_s=worksheet.Range[StartAddress,StartAddress];
				StartRowId=_range_s.Row;
				StartColId=_range_s.Column;
			}


			int arraywidth=dataobj.GetLength(1);
			int arrayheight=dataobj.GetLength(0);
			ArrayList ex_x = new ArrayList();
			ArrayList ex_y = new ArrayList();
			ArrayList ex_value = new ArrayList();
			object _fvalue="";
			int _maxlen=910;				
			for(int j=0;j<arrayheight;j++)
			{
				for(int k=0;k<arraywidth;k++)
				{
					_fvalue=dataobj[j,k];// field value
					if(_fvalue==null)
					{
						continue;
					}
					if(_fvalue.GetType().ToString()=="System.String")
					{
						if(((string)_fvalue).Length>_maxlen)
						{
							ex_x.Add(j+StartRowId);
							ex_y.Add(k+StartColId);
							ex_value.Add(_fvalue);
							_fvalue="";
						}// end maxlen 
					}
					dataobj[j,k]=(_fvalue.ToString().IndexOf("=")==0?"":AsString)+_fvalue;
				}//end columns
			}// end rows 
			
			if(DynamicCols==true)
			{
				srange=excel.Range[excel.Cells[StartRowId,StartColId],excel.Cells[StartRowId,StartColId]];
				for(int i=1;i<arraywidth;i++)
				{
					_range=excel.Range[excel.Cells[StartRowId,StartColId+i],excel.Cells[StartRowId,StartColId+i]];
					copyRangeStyle(srange,_range);
				}
			}
			
			object _copyheight=excel.Range[excel.Cells[StartRowId,StartColId],excel.Cells[StartRowId,StartColId+arraywidth-1]].RowHeight;

			
			if(drawtype==1)   //取startrow的格式
			{
				_range=excel.Range[excel.Cells[StartRowId+1,StartColId],excel.Cells[StartRowId+arrayheight-1,StartColId]];
				if(arrayheight>1)
				{
					_range.EntireRow.Insert(Excel.XlInsertShiftDirection.xlShiftDown,Type.Missing);
				}
				for(int i=0;i<arraywidth;i++)
				{
					srange=excel.Range[excel.Cells[StartRowId,StartColId+i],excel.Cells[StartRowId,StartColId+i]];
					_range=excel.Range[excel.Cells[StartRowId+1,StartColId+i],excel.Cells[StartRowId+arrayheight-1,StartColId+i]];
					copyRangeStyle(srange,_range);
				}
				_range=excel.Range[excel.Cells[StartRowId+1,StartColId],excel.Cells[StartRowId+arrayheight-1,StartColId+arraywidth-1]];
				_range.RowHeight=_copyheight;
			}
			
			_range=excel.Range[excel.Cells[StartRowId,StartColId],excel.Cells[StartRowId+arrayheight-1,StartColId+arraywidth-1]];
			_range.get_Resize(arrayheight,arraywidth);
			_range.set_Value(Excel.XlRangeValueDataType.xlRangeValueDefault,dataobj);


			
			for(int j=0;j<ex_value.Count;j++)
			{
				excel.Cells[ex_x[j],ex_y[j]]=ex_value[j].ToString();
			}

			if(DynamicCols==true)
			{
				if(DynamicColCfg!=null)
				{
					for(int j=0;j<DynamicColCfg.Count;j++)
					{
						_range=excel.Range[excel.Cells[StartRowId,StartColId+j],excel.Cells[StartRowId,StartColId+j]];
						object[] cfg=(object[])DynamicColCfg[j];
						string _title=cfg[0].ToString();
						_range.Value2=_title;
						_range=excel.Range[excel.Cells[StartRowId,StartColId+j],excel.Cells[65536,StartColId+j]];
						if(cfg.Length>1)
						{
							int _width=int.Parse(cfg[1].ToString());
							if(_width!=-1)
							{
								_range.ColumnWidth=_width;
							}
							else
							{
                                _range.ColumnWidth = 255;
								_range.Columns.AutoFit();
							}
						}
						if(cfg.Length>2)
						{
							_range.NumberFormatLocal=cfg[2].ToString();
						}
						//NumberFormatlocal						
					}
				}
			}




            if (WritePassword != "")
            {
                xb.WritePassword = WritePassword;
            }
            if (ProtectPassword != "")
            {
                worksheet.Protect(ProtectPassword);
                xb.Protect(ProtectPassword,true,true);

            }
            worksheet.SaveAs(@_lastfile, Missing.Value,WritePassword==""?(object)Missing.Value:(object)WritePassword, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
			xb.Close(null,null,null);
			excel.Workbooks.Close();
			int pid=0;
			IntPtr a = new IntPtr(excel.Parent.Hwnd);
			UInt32[] processId = new UInt32[1];
			GetWindowThreadProcessId((IntPtr)excel.Hwnd,processId);


			excel.Quit();

			if(worksheet != null)
			{
				System.Runtime.InteropServices.Marshal.ReleaseComObject(worksheet);
				worksheet = null;
			}
			if(xb != null)
			{
				System.Runtime.InteropServices.Marshal.ReleaseComObject(xb);
				xb = null;
			}
			if(excel != null)
			{
				System.Runtime.InteropServices.Marshal.ReleaseComObject(excel);
				excel = null;
			}
			GC.Collect();
			

			KillProcessByStartTime("EXCEL",beforetime,aftertime);
			

			return _lastfile;

			
		}

public string KillProcessByStartTime(string processName,DateTime beforetime,DateTime aftertime)
		{
			Process[] ps = Process.GetProcesses();
			foreach (Process p in ps)  
			{
				if(p.ProcessName.ToUpper()!=processName) continue;
				if(p.StartTime > beforetime && p.StartTime < aftertime)
				{
					try
					{
						p.Kill();
					}
					catch(Exception e)
					{
						return e.Message;
					}
				}
			}  
			return "";
		}

调用示例

我们设计Web应用中的输出模板(Request.PhysicalApplicationPath + "\\bfile\\excel\\模板.xlsx"),如下图:

39923a9f7e9a43e2939112cca8ee9a66.png

如图  <%system.excel.title.dyna.by.craneoffice%> ,表示要替换的标题 key ,下面的二维表格,表示预设好的输出列,下面的行即为数据输出行,在这里,我们预设要从第1列第5行输出数据。以下是调用的示例代码:

 

object[,] rv = DataSetToOject();    //这个是初始化二维数据数组的

    string[,] _repls = new string[1, 2];
    _repls[0, 0] = "<%system.excel.title.dyna.by.craneoffice%>";
    _repls[0, 1] = "考察对象家庭成员及主要社会关系人基本情况";

    string ModuleFile = Request.PhysicalApplicationPath + "\\bfile\\excel\\模板.xlsx";
    string _lastfile = er.Jree(@ModuleFile, rv, 1, 5, 1, _repls, 1, true, false, null);
    string _url = "/bfile/excel/tempbfile/" + Path.GetFileName(_lastfile);
    

_lastfile 为最终生成的 excel 数据导出文件全路径地址,_url 为转化的可下载URL地址。 

 

总结

为保持兼容性,本方法支持旧版本的Word97-2003格式,如需要突破65536行限制,我们可以根据实际需要进行设计调整。

本方法支持数据输出行样式的持续复制,即我们可以设置单行样式(如字体大小、颜色、边框等),方法会根据数据行数,循环复制样式进行行输出 。

我们在此仅根据实际项目需要,讲述了一些导出数据到Excel的参数需求,这里仅作参考,欢迎大家评论指教!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2138007.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于TCP的网络计算器实现

目录 一. 重新理解协议 二. 序列化与反序列化 2.1 概念 2.2 重新理解 read、write、recv、send 和 tcp 为什么支持全双工 2.3 理解TCP面向字节流 三. 请求应答模块实现 3.1 添加与解析报头 3.2 定制协议&#xff1a; 3.3 Json 四. 计算模块实现…

字典转换(根据字典转换、根据id转换)

一、三种转换方式 翻译场景:序列化时候转换 适用类型: 字典type转中文用户id转用户名部门id转名称附件id转url路径1.1 根据另一个映射字段 翻译保存到此字段 根据创建者createBy的id,查询名称设置到 createName 1.2 直接根据此字段值翻译后替换此字段值 ossId 替换为 url …

医疗监测数据检测系统源码分享

医疗监测数据检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

vue3透传、注入

属性透传 传递给子组件时&#xff0c;没有被子组件消费的属性或事件&#xff0c;常见的如id、class 注意1 1.class、style是合并的&#xff0c;style中如果出现重复的样式&#xff0c;以透传属性为准2.id属性是以透传属性为准&#xff0c;其他情况透传属性名相同&#xff0c…

深度学习云服务器免费使用教程

#云服务器# #深度学习# #人工智能# #计算机视觉# 本文为各位学习深度学习的入门选手而创建&#xff0c;降低深度学习的入门门槛。 谷歌云服务器Colab&#xff1a; T4GPU。限额&#xff0c;需要科学上网&#xff0c;不能使用终端。 谷歌云服务器地址&#xff1a;欢迎使用 C…

C语言 | Leetcode C语言题解之第405题数字转换为十六进制数

题目&#xff1a; 题解&#xff1a; char * toHex(int num){int i0;char *nums(char*)malloc(sizeof(char)*32);unsigned int newnum(unsigned int)num;if(num0){nums[0]0;nums[1]\0;return nums;}while(newnum>1){int flagnewnum%16;newnum/16;if(flag<9){nums[i]flag0…

华为OD机试 - 计算误码率(Python/JS/C/C++ 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

Acwing 队列

模拟队列 主要思想&#xff1a;先进先出&#xff08;注意与栈做区分&#xff09;&#xff0c;队尾插入&#xff0c;队头删除。设置一个数组存储数据&#xff0c;队头指针指向队列第一个元素&#xff08;初始为0&#xff09;&#xff0c;队尾指针指向最后一个元素&#xff08;初…

Qt常用控件——QSpinBox

文章目录 QSpinBox核心属性及信号点餐示例 QSpinBox核心属性及信号 QSpinBox或者QDoubleSpinBox表示微调框&#xff0c;带有按钮的输入框&#xff0c;可以用来输入整数/浮点数或者通过点击按钮调整数值大小 QSpinBox和QDoubleSpinBox用法基本相同&#xff0c;本篇以QSpinBox为…

Ubuntu 安装包下载(以20版本 阿里镜像站为例子)

Ubuntu安装包下载 上一篇文章写了一些国内常用的镜像站&#xff0c;这篇以阿里云镜像站Ubuntu20版本为例。 https://mirrors.aliyun.com/ubuntu-releases/ 1.点击自己想要下载的版本 2.点击以amd64.iso为结尾的文件&#xff0c;这个是安装文件&#xff0c;如果是桌面端&…

C++初阶学习——探索STL奥秘——vector的模拟实现

vector的结构比较特殊&#xff0c;成员变量为三个指针 #pragma once #include <iostream> using std::cin; using std::cout; using std::endl;#include <string> using std::string;namespace Yohifo {template<class T>class vector{public:typedef T val…

使用jmeter做性能测试实践过程中需要注意什么

前言 在驾驭Apache JMeter进行性能测试之旅中&#xff0c;深刻理解其特性和限制是至关重要的。以下是提升JMeter效能的关键策略&#xff0c;旨在挖掘其潜力&#xff0c;克服局限&#xff0c;实现精准测试。 1.精确调控线程数 推荐阈值&#xff1a;将线程数控制在300以内&…

模拟视频推到WVP推流列表

效果 1. wvp创建RTMP 2. 使用ffmpeg将本地的视频转为rtmp ffmpeg -re -i F:rtsp\123.mp4 -c copy -f flv rtmp://192.168.1.237:1935/cd/10001?sign=Z4Y3eYeSg

HTML5之canvas绘图

介绍 <canvas> 是 HTML5 引入的一个强大元素&#xff0c;允许直接在网页上进行矢量图形和位图图像的绘制&#xff0c;为网页提供了一个动态图形渲染的平台。这一特性极大丰富了网页的表现力&#xff0c;特别是在数据可视化、游戏开发、交互式图表和动画制作等领域发挥着…

第311题| 超好用!二重积分求旋转体体积公式|武忠祥老师每日一题

第一步&#xff1a; &#xff08;1&#xff09;找渐近线&#xff0c;先看水平渐近线&#xff0c;看x趋于无穷时&#xff0c;y有没有趋于一个有限的值。 , 得出水平渐近线y1。因为左右两边都是水平渐近线&#xff0c;所以没有斜渐近线。 第二步&#xff1a; 画出图像&#…

Spring Boot环境下的学生读书笔记共享

第4章 系统设计 4.1系统结构设计 读书笔记共享平台的设计主要是为了满足用户的实际需求。 因此&#xff0c;它需要通过Internet实现&#xff0c;因此它必须具备硬件和软件基础。该平台最终可以通过科学技术和各种方式达到支持智能化的信息管理的目的。因此&#xff0c;它必须具…

深入理解Python中的生成器:高效迭代与延迟计算的艺术

在处理大量数据时&#xff0c;如何有效地管理内存成为了一个关键问题。Python中的生成器&#xff08;Generator&#xff09;提供了一种优雅的解决方案&#xff0c;它允许你在迭代过程中按需生成数据&#xff0c;而不是一次性加载所有数据到内存中。本文将详细探讨生成器的工作原…

看Threejs好玩示例,学习创新与技术(三)

本文接上篇内容&#xff0c;继续挖掘应用ThreeJS的一些创新算法。 1、获得鼠标移动对应的地理位置 这个算法如果放在几年前&#xff0c;那肯定会难倒一帮人的。因为是三维投影涉及矩阵变换及求逆&#xff0c;而且还是投影模式下的。在Project Texture这个示例中&#xff0c;作…

Sentaurus TCAD的sdevice求解中选择Math求解方法

目录 并行迭代线性求解器&#xff08;ILS&#xff09;并行超节点直接求解器&#xff08;ParDiSo&#xff09;超节点直接求解器&#xff08;Super&#xff09;详细解释1. 并行迭代线性求解器&#xff08;ILS&#xff09;2. 并行超节点直接求解器&#xff08;ParDiSo&#xff09;…

windows安装docker、elasticsearch、kibana、cerebro、logstash

文章目录 1. 安装docker1.1. 两大要点1.1.1. 安装启用hyper-v电脑不存在hyper-v的情况 1.1.2. 下载安装docker 2. 在docker里面安装elasticSearch&#xff0c;kibana&#xff0c;cerebro3. 安装logstash-将数据导入到elasticSearch3.1 安装logstash3.1.1 注意事项3.1.1.1. 等了…