EXCEL(带图)转html【uni版】

文章目录

一、前言

之前写过一个 bootstrap 版本的,但这次实现在APP上,就只有重写前端,后端也得变一变。
思路 用tab-bar 实现sheet的切换,兼容图片显示。
难点是 uni-table的后置渲染在v-html里并不上很顺利。

二、后端(.net8)

csharp 复制代码
 /// <summary>
 /// 表格
 /// </summary>
 public static string excel(string filePath)
 {
     IWorkbook workbook;
     using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
     {
         if (Path.GetExtension(filePath) == ".xls")
             workbook = new HSSFWorkbook(fs); // 处理 Excel 2003
         else
             workbook = new XSSFWorkbook(fs); // 处理 Excel 2007+
     }

     StringBuilder htmlBuilder = new StringBuilder();
     for (int i = 0; i < workbook.NumberOfSheets; i++)
     {
         ISheet sheet = workbook.GetSheetAt(i);
         htmlBuilder.AppendFormat(sheet.SheetName + ",");
     }
     htmlBuilder.Append(" [temp]");

     for (int i = 0; i < workbook.NumberOfSheets; i++)
     {
         htmlBuilder.Append($"<table id='dtable{i}'  border >");
         ISheet sheet = workbook.GetSheetAt(i);

         //标记插入图片后导致的位移
         List<tude> InImg = new List<tude>();
         //最大列、最大行
         int maxcol = 0; int maxrow = sheet.LastRowNum;

         //图片不占单元格,但是需要循环到位置
         if (sheet is XSSFSheet xssfSheet2)
         {
             if (xssfSheet2.GetDrawingPatriarch() != null)
             {
                 foreach (var drawing in xssfSheet2.GetDrawingPatriarch().GetShapes())
                 {
                     if (drawing is XSSFPicture picture)
                     {
                         int m1 = picture.ClientAnchor.Col2;
                         int m2 = picture.ClientAnchor.Row2;
                         if (m1 > maxcol) maxcol = m1;
                         if (m2 > maxrow) maxrow = m2;
                     }
                 }
             }
         }

         for (int x = 0; x < maxrow; x++)//行
         {
             IRow row = sheet.GetRow(x);
             htmlBuilder.Append("<tr>");

             if (x == 0)//没图片就取第一行列数
             { if (row.LastCellNum > maxcol) maxcol = row.LastCellNum; }
             for (int j = 0; j < maxcol; j++)//列
             {
                 ICell cell; string cellValue;

                 if (row != null)
                 {
                     cell = row.GetCell(j);
                     cellValue = cell?.ToString() ?? "";
                 }
                 else cellValue = "";

                 // 检查单元格是否包含图片
                 bool hasImage = false;
                 if (sheet is XSSFSheet xssfSheet)
                 {
                     if (xssfSheet.GetDrawingPatriarch() != null)
                     {
                         foreach (var drawing in xssfSheet.GetDrawingPatriarch().GetShapes())
                         {
                             int nowrow = 0; int nowcol = 0;
                             if (drawing is XSSFPicture picture)
                             {
                                 if (picture.ClientAnchor.Col1 == j && picture.ClientAnchor.Row1 == x)
                                 {
                                     byte[] imageBytes = ((XSSFPicture)drawing).PictureData.Data;
                                     string base64Image = Convert.ToBase64String(imageBytes);
                                     string imageFormat = ((XSSFPicture)drawing).PictureData.MimeType.Split('/')[1];
                                     cellValue = $"<img src='data:image/{imageFormat};base64,{base64Image}'/>";
                                     hasImage = true;
                                     nowrow = picture.ClientAnchor.Row2 - picture.ClientAnchor.Row1;//图片占几行
                                     nowcol = picture.ClientAnchor.Col2 - picture.ClientAnchor.Col1;//图片占列行
                                                                                                    //标记坐标,解决多行多列导致的位移
                                     for (int a = picture.ClientAnchor.Row1; a <= picture.ClientAnchor.Row2; a++)//行
                                     {
                                         for (int b = picture.ClientAnchor.Col1; b <= picture.ClientAnchor.Col2; b++)//列
                                         {
                                             tude t = new tude();
                                             t.xx = b;//列 x
                                             t.yy = a;//行 y
                                             InImg.Add(t);
                                         }
                                     }

                                     if (hasImage)
                                         htmlBuilder.AppendFormat("<td rowspan='{1}'  colspan='{2}' >{0}</td>", cellValue, nowrow, nowcol);
                                 }
                             }
                         }
                     }
                 }
                 if (!hasImage)
                 {
                     if (InImg.Where(p => p.xx == j & p.yy == x).ToList().Count > 0) { }//坐标校对 是否被图片占用
                     else
                     {
                         htmlBuilder.AppendFormat("<td>{0}</td>", cellValue);
                     }
                 }

             }
             htmlBuilder.Append("</tr>");
         }
         //整个sheet没有内容,只有图
         if (maxcol == 0 && maxrow == 0)
         {
             if (sheet is XSSFSheet xssfSheet)
             {
                 foreach (var drawing in xssfSheet.GetDrawingPatriarch().GetShapes())
                 {
                     htmlBuilder.Append("<tr>");
                     if (drawing is XSSFPicture picture)
                     {
                         byte[] imageBytes = ((XSSFPicture)drawing).PictureData.Data;
                         string base64Image = Convert.ToBase64String(imageBytes);
                         string imageFormat = ((XSSFPicture)drawing).PictureData.MimeType.Split('/')[1];
                         string cellValue = $"<img src='data:image/{imageFormat};base64,{base64Image}'/>";
                         htmlBuilder.AppendFormat("<td>{0}</td>", cellValue);
                     }
                     htmlBuilder.Append("</tr>");
                 }
             }
         }

         htmlBuilder.Append("</table>");
         htmlBuilder.Append("[item]");
     }

     return htmlBuilder.ToString();
 }

三、前端(uniapp)

typescript 复制代码
<template>
	
	<view class="tabs">
		<scroll-view id="tab-bar" class="scroll-h" :scroll-x="true" :show-scrollbar="false"
			:scroll-into-view="scrollInto">
			<view v-for="(tab,index) in tabBars" :key="index" class="uni-tab-item" :id="index-1" :data-current="index"
				@click="ontabtap">
				<text class="uni-tab-item-title"
					:class="tabIndex==index ? 'uni-tab-item-title-active' : ''">{{tab}}</text>
			</view>
		</scroll-view>
		<view class="line-h"></view>
		<view  class="swiper-box" >
			<view class="swiper-item " v-for="(tab,index1) in contents" :key="index1">
				<scroll-view  class="uni-container" :scroll-x="true"  :scroll-Y="true" v-show="index1==tabIndex" >
				  <view v-html="tab"  class="uni-table" ></view> <!-- 动态渲染内容 --> 
				</scroll-view>
			</view>
		</view>
	</view>
</template>
<script >
	export default {
		data() {
			return {
				contents: [],
				cacheTab: [],
				tabIndex: 0,
				tabBars: [],
				scrollInto: "",
				showTips: false,
				navigateFlag: false,
				pulling: false,
				refreshIcon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAB5QTFRFcHBw3Nzct7e39vb2ycnJioqK7e3tpqam29vb////D8oK7wAAAAp0Uk5T////////////ALLMLM8AAABxSURBVHja7JVBDoAgDASrjqj//7CJBi90iyYeOHTPMwmFZrHjYyyFYYUy1bwUZqtJIYVxhf1a6u0R7iUvWsCcrEtwJHp8MwMdvh2amHduiZD3rpWId9+BgPd7Cc2LIkPyqvlQvKxKBJ//Qwq/CacAAwDUv0a0YuKhzgAAAABJRU5ErkJggg=="
			}
		},
		onLoad(o) {
			//let data = "D:\\file\\3.xlsx"
			let url=o.url;
			this.LoadFile(url)
		},
		onNavigationBarButtonTap(e) {
			this.navTo('scan');
		},
		onBackPress(options) {
			this.navTo(this.$assist.gdata("mypage"))
			// 阻止默认返回行为
			return true;
		},
		methods: {
			ontabtap(e) {
				let index = e.target.dataset.current || e.currentTarget.dataset.current;
				this.switchTab(index);
			},
			async navTo(url) {
				this.$mRouter.push({
					route: url
				});
			},
			/*
			ontabchange(e) {
			    let index = e.target.current || e.detail.current;
			    this.switchTab(index);
			},
			*/
			switchTab(index) {
				if (this.tabIndex === index) {
					return;
				}
				this.tabIndex = index;
				//this.scrollInto = this.tabBars[index].id;
                console.log(this.tabIndex)
			}, //加载表格
			LoadFile(dataurl) {
				let obj = {};
				obj.str = dataurl;
				obj.uid=this.$assist.gdata("user").id;
				const toData = JSON.stringify(obj);
				const params = {
					"object": "File",
					"method": "EXCEL",
					"data": toData,
				}
				this.$request({
					data: params
				}).then((res) => {
					if (res.data == 'noroot') {
						this.$assist.showNo(this.$t("file.t1"));
					} else if (res.data == 'nosrc') {
						this.$assist.showNo(this.$t("file.t2"));
					} else {
						let content = res.data;
						 this.$nextTick(() => {
						 this.tabBars = content.split('[temp]')[0].split(',');
						 this.contents = content.split('[temp]')[1].split('[item]');
						})
					}

				}, err => {
						this.$assist.showNo(this.$t("login.t5"));
				})
			},

		}
	}
</script>

<style lang="scss" scoped>
	/* #ifndef APP-PLUS */
	page {
		width: 100%;
		min-height: 100%;
		display: flex;
	}

	/* #endif */

	.tabs {
		flex: 1;
		flex-direction: column;
		overflow: hidden;
		background-color: #ffffff;
		/* #ifndef APP-PLUS */
		height: 100vh;
		/* #endif */
	}

	.scroll-h {
		// width: 750rpx;
		width: 100%;
		height: 80rpx;
		flex-direction: row;
		white-space: nowrap;
		/* flex-wrap: nowrap; */
		/* border-color: #cccccc;
		border-bottom-style: solid;
		border-bottom-width: 1px; */
	}

	.line-h {
		height: 1rpx;
		background-color: #cccccc;
	}

	.uni-tab-item {
		display: inline-block;
		flex-wrap: nowrap;
		padding-left: 34rpx;
		padding-right: 34rpx;
	}

	.uni-tab-item-title {
		color: #555;
		font-size: 30rpx;
		height: 80rpx;
		line-height: 80rpx;
		flex-wrap: nowrap;
		/* #ifndef APP-PLUS */
		white-space: nowrap;
		/* #endif */
	}

	.uni-tab-item-title-active {
		color: #007AFF;
	}
    
	.swiper-box {
		flex: 1;
	}
	uni-swiper{
		height: 550px !important;
	}
	.uni-container{
		height: 550px !important;
	}

	/* .swiper-item {
		flex: 1;
		flex-direction: row;
	} */

	.scroll-v {
		flex: 1;
		/* #ifndef MP-ALIPAY */
		flex-direction: column;
		/* #endif */
		width: 750rpx;
		width: 100%;
	}
	/* 手动添加 uni-table 样式 */
::v-deep  .uni-table table {
  width: 200%;
  border: 1px solid #d7d9df ;
  border-collapse: collapse;
}
.uni-table th, 
::v-deep  .uni-table td {
  border: 0px ;
  border-left: 1px solid #d7d9df ;
  border-bottom: 1px solid #d7d9df ;
  padding: 8px;
}

</style>
相关推荐
我家媳妇儿萌哒哒2 小时前
Vue2 elementUI年份区间选择组件
前端·javascript·elementui
**蓝桉**2 小时前
EXCEL 函数
excel
笨笨狗吞噬者3 小时前
【uniapp】小程序体积优化,分包异步化
前端·微信小程序·uni-app
该用户已不存在3 小时前
Golang 上传文件到 MinIO?别瞎折腾了,这 5 个库拿去用
前端·后端·go
snows_l3 小时前
JavaScript 性能优化实战大纲
前端
文心快码BaiduComate3 小时前
文心快码3.5S开发古风射覆小游戏,它帅到我了!
前端·后端·程序员
佛系菜狗3 小时前
防抖和节流-防抖鸿蒙版本实现
前端
不一样的少年_4 小时前
老板问我:AI真能一键画广州旅游路线图?我用 MCP 现场开图
前端·人工智能·后端
东方石匠4 小时前
Javascript常见面试题
前端·javascript·面试