2023年2月

在做响应式页面的时候,往往需要考虑更多尺寸设备的界面兼容性,一般不能写死像素,以便能够使得界面元素能够根据设备的不同进行动态调整,但往往有时候还是碰到一些问题,如Tab标签第一页面正常显示,但是切换其他页面的时候显示内容没有发生动态的调整,本篇随笔介绍解决Tab标签页切换图表显示问题,以及图表控件可以实现窗口动态变化进行调整尺寸。

1)常规的图表处理

例如下面界面有两个Tab标签页,如下所示,第一个标签页显示正常。

部分界面代码如下所示

<divclass="portlet-body">
    <divclass="tab-char"id="lineContainer1"style="height:300px;max-width:500px;"></div>
</div>

如果我们在基于IPhone的模拟设备尺寸查看的时候,会发现图片并未能进行有效的缩放以正确的方式显示,也就是在Tab标签页切换的时候,第二个标签页的图表的尺寸无法正确的缩放。

那么我们如果要实现在标签页切换的时候,我们能够获得正确的效果的时候,那么需要跟踪标签页的切换事件进行处理。

在网上搜索了一下解决方案,其中有一篇《
解决Bootstrap 标签页(Tab)插件切换echarts不显示问题
》随笔介绍的思路也挺好的。

不过我进行了一些合并改造,其实也是实现了他说的几个要点,不过更加简化而已:

1. bootstrap实现响应式布局
2. highcharts实现自适应
3. 标签页切换、缩放正常显示

我这里利用的是HighChart图表控件,不过原理是一样的,我们需要对图表集合进行一个遍历处理,只不过遍历的处理可以使用更加方便的JQuery文档查找方式。

2、解决Tab标签页切换图表显示问题

例如我的图表声明,以及动态获取图表数据的代码如下所示:

    //初始化对象
    $(function() {var chart1 = newHighcharts.Chart({
chart: {
renderTo:
"container1",
plotBackgroundColor:
null,
plotBorderWidth:
null,
plotShadow:
false,
},
title: {
text:
'集团分子公司人员组成'},
tooltip: {
pointFormat:
'{series.name}: <b>{point.y}</b>'},
plotOptions: {
pie: {
allowPointSelect:
true,
cursor:
'pointer',
dataLabels: {
enabled:
true,
format:
'<b>{point.name}</b>: {point.percentage:.1f} %',
style: {
color: (Highcharts.theme
&& Highcharts.theme.contrastTextColor) || 'black'}

},
//showInLegend: true }
},
series: [{
type:
'pie',
name:
'人员数量',
data: []
}]
});
//通过Ajax获取图表1数据 $.ajaxSettings.async = false;var data1 =[];
$.getJSON(
"/User/GetCompanyUserCountJson", function(dict) {for (var key indict) {if(dict.hasOwnProperty(key)) {
data1.push([key, dict[key]]);
}
};
chart1.series[
0].setData(data1);
});

这部分做参考了解即可,真正起作用的不是这些代码。

真正起作用的是,我们利用Boostrap的Tab变化的事件进行处理,如下所示。

        //TAB页面变化的时候,调整图表宽度
        $('.grid_tab').on('shown.bs.tab', function() {var target = $(this).attr('href');var controls = $(target).find('.tab-char');for(var i=0;i<controls.length; i++)
{
$(controls[i]).highcharts().reflow();
}
});
//窗口大小变化的时候,调整图表宽度 $(window).resize(function() {var controls = $(document).find('div.tab-char');for (var i = 0; i < controls.length; i++) {
$(controls[i]).highcharts().reflow();
}
});

上面的那段JS,是利用了JQuery动态遍历出相应的highcharts对象,然后调用它的.reflow() 函数进行更新即可。

参考下图表的Tab标签页的HTML代码,我们注意到 class="tab-pane”  和  class="tab-char"的两个DIV层,这些就是我们利用JQuery来动态查找图表控件并进行处理的关键。

           <divclass="tab-pane fade active in"id="tab_2_1">
                <divclass="row">
                    <divclass="col-md-6 col-sm-6">
                        <divclass="portlet light ">
                            <divclass="portlet-title">
                                <divclass="caption">
                                    <iclass="icon-bar-chart font-green-sharp hide"></i>
                                    <spanclass="caption-subject font-green-sharp bold uppercase">图表1</span>
                                </div>
                                <divclass="actions">
                                    <divclass="btn-group btn-group-devided"data-toggle="buttons">
                                        <labelclass="btn btn-transparent purple btn-circle btn-sm active">
                                        <inputtype="radio"name="options"class="toggle"id="option1">更多...</label>
                                    </div>
                                </div>
                            </div>
                            <divclass="portlet-body">
                                <divclass="tab-char"id="container1"style="height: 300px;max-width:500px"></div>
                            </div>
                        </div>
                    </div>
                    <divclass="col-md-6 col-sm-6">
                        <divclass="portlet light ">
                            <divclass="portlet-title">
                                <divclass="caption">
                                    <iclass="icon-bar-chart font-green-sharp hide"></i>
                                    <spanclass="caption-subject font-green-sharp bold uppercase">3D图表2</span>
                                </div>
                                <divclass="actions">
                                    <divclass="btn-group btn-group-devided"data-toggle="buttons">
                                        <labelclass="btn btn-transparent purple btn-circle btn-sm active">
                                            <inputtype="radio"name="options"class="toggle"id="option1">更多...</label>
                                    </div>
                                </div>
                            </div>
                            <divclass="portlet-body">                                
                                <divclass="tab-char"id="container2"style="height: 300px;max-width:500px"></div>
                            </div>
                        </div>
                    </div>

如果我们在处理jS的时候,无法确定是否正确运行了,我们可以跟踪函数,并可以跟踪获得对应的对象情况,如下我是在Chrome里面进行跟踪获得的结果,并可以跟踪进去每一步。

或者可以看看窗口变化的时候,我们捕获的对象。

获得对象后,我们转换为对应的控件,然后调用它的接口进行更新即可。

$(controls[i]).highcharts().reflow();

以上就是我们实现的思路和跟踪处理办法,最后上图说明问题解决。

最近到客户处进行实地培训,整理了很多培训的材料,现将它们录制相关主题的视频,作为我的Bootstrap开发框架的知识补充,希望给感兴趣的朋友进行了解。培训内容主要包括基础框架部分、MVC框架部分、Bootstrap框架部分、Bootstrap重要插件使用等相关的内容。

其中内容中的基础框架部分提纲如下所示。

其中MVC框架部分的提纲如下所示。

其中Bootstrap介绍的提纲如下所示。

其中Bootstrap重要插件使用的提纲如下所示。

这几个部分的视频我录制并上传到了腾讯视频里面了,大家如果有兴趣,可以通过我们的小程序进行在线视频学习。

扫描下面的小程序码,然后进入视频教程模块即可查看。


当然也可以在腾讯视频网站中直接查找,然后进行播放学习。

在很早之前就介绍过图表插件Highcharts的使用了,在2014年的随笔《
基于MVC4+EasyUI的Web开发框架经验总结(4)--使用图表控件Highcharts
》,这里基本上都介绍的比较完整,基本的设置也没有太大的差异,本篇介绍的是基于Bootstrap开发框架的界面处理,以及对图表插件Highcharts的其他模块,如柱状图,线图等其他样式的信息进行动态设置,以期达到利用数据库的数据,方便动态设置显示出来。

1、Bootstrap框架图标的展示

饼图的数据展示界面效果如下所示

柱状图以及其他曲线图展示效果如下所示。

使用这些图表功能强,我们一般需要在页面里面引入对应的JS+CSS

2、使用脚本动态设置图表的数据

默认的案例,这些数据都是直接绑定在里面的,有时候我们需要动态设置,那么需要分析好对应的数据属性,以及设置的API,才能正常进行显示。

以饼图为例,我们需要分析它的数据结构,一般是Series里面的Data数据格式,不同的图表样式需要的数据结构不太一样,对于图表而已,它的数据格式如下所示。

另外也可以使用key、Value方式的定义格式,如下数据所示。

那么,有了这些了解,我们就可以通过Ajax方式,动态从数据库里面获取数据,并绑定在界面上显示即可。

首先我们定义好界面上的一个图表展示控件DIV层,如下代码所示。

<divclass="tab-char"id="container1"style="height: 300px;max-width:500px"></div>

然后通过JS动态创建对应的图表对象,并设置图表的数据即可。

       var chart1 = newHighcharts.Chart({
chart: {
renderTo:
"container1",
plotBackgroundColor:
null,
plotBorderWidth:
null,
plotShadow:
false,
},
title: {
text:
'集团分子公司人员组成'},
tooltip: {
pointFormat:
'{series.name}: <b>{point.y}</b>'},
plotOptions: {
pie: {
allowPointSelect:
true,
cursor:
'pointer',
dataLabels: {
enabled:
true,
format:
'<b>{point.name}</b>: {point.percentage:.1f} %',
style: {
color: (Highcharts.theme
&& Highcharts.theme.contrastTextColor) || 'black'}
},
//showInLegend: true }
},
series: [{
type:
'pie',
name:
'人员数量',
data: []
}]
});

动态构建数据是通过Ajax方式实现的,如下所示。

        //通过Ajax获取图表1数据
        $.ajaxSettings.async = false;var data1 =[];
$.getJSON(
"/User/GetCompanyUserCountJson", function(dict) {for (var key indict) {if(dict.hasOwnProperty(key)) {
data1.push([key, dict[key]]);
}
};
chart1.series[
0].setData(data1);
});

这里值得注意的是,我们获取一个图表对象,是通过下面代码方式获取才行

 var chart1 = new Highcharts.Chart({

这种方式可以获得对应的chart1对象,并进行设置图表属性或者调用API接口。

又如对于传入一个数组对象的图表

它的动态设置数据的代码如下所示。

        var chart4 = newHighcharts.Chart({
chart: {
renderTo:
'container4',
type:
'column',
margin:
75,
options3d: {
enabled:
true,
alpha:
15,
beta:
15,
depth:
50,
viewDistance:
25}
},
title: {
text:
'Chart rotation demo'},
subtitle: {
text:
'Test options by dragging the sliders below'},
plotOptions: {
column: {
depth:
25}
},
series: [
{
data:
null//[29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4] }
]
});
//模拟动态设置,chartData数据可以通过Ajax动态获取 var chartData = [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4];
chart4.series[
0].setData(chartData);

如果对于柱状图的数据,我们又是需要分析它的数据结构,然后进行相应的数据的

柱状图的数据格式大概如下所示。

完整的柱状图JS对象处理代码如下所示。

        //柱状图的展示
        var linechart1 = newHighcharts.Chart({
chart: {
renderTo:
'lineContainer1',
type:
'column',
},
title: {
text:
'销售出货日报表'},
xAxis: {
categories: []
//['Apples', 'Oranges', 'Pears', 'Grapes', 'Bananas'] },
yAxis: {
allowDecimals:
false,
min:
0,
title: {
text:
'销售金额'}
},
tooltip: {
formatter:
function() {return '<b>' + this.x + '</b><br/>' + this.series.name + ': ' + this.y + '<br/>' + 'Total: ' + this.point.stackTotal;
}
},
plotOptions: {
column: {
stacking:
'normal'}
},
series: [
//{ //name: 'John', //data: [5, 3, 4, 7, 2], //stack: 'male' //}, { //name: 'Joe', //data: [3, 4, 4, 2, 5], //stack: 'male' //}, { //name: 'Jane', //data: [2, 5, 6, 2, 1], //stack: 'female' //}, { //name: 'Janet', //data: [3, 0, 4, 4, 3], //stack: 'female' //} ]
});

我们上面注释掉的 categories 和 series 数据,就是为了让我们方便通过JS脚本动态添加进去,实现图标数据的动态化设置的。

例如对于销售出货数据的统计,我们模拟的部分数据来进行展示。

        //设置数据,这里可以通过JSON获取
        var category = ['2018-7-1', '2018-7-2', '2018-7-3', '2018-7-4', '2018-7-5'];var seriesData =[{
name:
'AB',
data: [
500, 300, 400, 700, 200]
}, {
name:
'BC',
data: [
300, 400, 400, 200, 500]
}, {
name:
'CD',
data: [
200, 500, 600, 200, 100]
}, {
name:
'EF',
data: [
300, 0, 400, 400, 300]
}];
//先移除选来的series对象,然后加入 while (linechart1.series.length > 0) {
linechart1.series[
0].remove(true);
}
for (var i = 0; i < seriesData.length; i++) {//加入categories linechart1.xAxis[0].setCategories(category);//加入series linechart1.addSeries(seriesData[i]);
}

通过这样的处理,我们的数据就可以实现动态的显示了。

其他的图表也是通过类似的方式,通过获取到对应的图表对象,然后动态构建数据,并将数据设置到对应的图表属性上即可。

这样处理方式的差异,我们也可以参考下官网提供的一些属性或者接口的定义来进行处理,本篇案例也是综合了很多其他例子的说明进行测试,并获得正常的数据展示效果。

本篇主要介绍Highcharts插件的动态设置属性的处理,对于其他图表插件,如EChart等也是一个很好的参考,比较图表的数据格式都是很接近的。

因客户需要实现PDF的预览处理,在网上找了一些PDF在线预览的解决方案,有的用PDFJS的在线预览方式,有的使用PDFObject的嵌入式显示,有的通过转换JPG/PNG方式实现间接显示的方式,开始是想通过简单的方式,能够使用JS插件实现预览最好,可是在线预览总是有一些不足,如不同浏览器的兼容问题,甚至不同的手机平台中展示的效果也不一样,不过最好还是采用了间接的方式,把PDF转换为图片展示效果,达到客户的要求。

1、在线实现预览的方式

一开始我还是很倾向使用这种方式,希望能采用一个较为好的JS插件的方式,实现PDF的在线预览(通过Web预览),因此在Github上找到排名比较高的PDF插件

一看排名还是很高的,那么采用它应该不错,查看自带的PDF文件,效果还是杠杠的。

不过客户的要求是显示正常的发票PDF文件,换一下文件地址,有部分信息显示不了,找了一下没有看到解决方法,所以效果不达标。

连基本的发票也显示不了,那我这个就不能用它来显示发票PDF文件了。

最后,测试了使用PDFObject(
https://pdfobject.com/
)的方式实现在线嵌入PDF显示的方式,这个JS插件也是不错的,同样可以在GitHub上可以找到。

它的使用也是很简单的,如下代码所示。

<scriptsrc="/js/pdfobject.js"></script>
<script>PDFObject.embed("/pdf/sample-3pp.pdf","#example1");</script>

如果需要设置预览窗口的大小,通过设置样式即可。

<style>.pdfobject-container{height:500px;}.pdfobject{border:1px solid #666; }
</style>

显示的效果是正常的了,不过我在苹果手机打开Safari浏览器测试发现,不能正常显示。

因此也不能使用来进行预览显示。

在实际的测试中,发现安卓手机的浏览器对于预览PDF也是支持不一,有些直接下载PDF,不支持预览显示。

为了避免这些问题,最好找了一个折中的方案,把PDF转换为图片进行显示,图片在不同的浏览器中显示可是没有问题的。

2、PDF转换图片进行显示

把PDF转换为图片也有很多控件处理,例如Aspose.Pdf、Spire.Pdf、 pdfiumviewer 等等,不同的第三方类库使用的方法有所差异,不过思路都很类似。

本来倾向于使用Aspose.Pdf的,不过发现转换后的发票信息还是缺失了某些中文字符或者乱码,导致不能正常显示。

后来寻找Spire.Pdf 版本以及对应的绿色版本,终于能够转换为正确的格式了,因此也就使用这个第三方控件进行转换图片使用了。

至于在线预览,我们在第一次请求PDF预览文件的时候,生成对应的图片文件,后面直接返回路径即可。

实现的预览效果如下所示。

由于我们是在asp.net MVC的项目上进行显示的,因此需要修改控制器的处理逻辑,对图片的生成进行判断处理即可。

控制器后台的实现代码如下所示。

                //判断是否存在PDF生成的图片文件,//生成的jpg文件名为附件的ID
                string pdfjpgPath = string.Format("/GenerateFiles/pdf/{0}.jpg", info.ID);string pdfjpg =Server.MapPath(pdfjpgPath);//PDF文件路径,相对目录即可
                string pdfPath = @"/Content/Template/fapiao.pdf";string pdfRealPath =Server.MapPath(pdfPath);//如果不存在,则生成,否则返回已生成的文件
                if(!FileUtil.IsExistFile(pdfjpg))
{
//破解 ModifyInMemory_Spire.ActivateMemoryPatching();
PdfDocument doc
= newPdfDocument(pdfRealPath);var image = doc.SaveAsImage(0, Spire.Pdf.Graphics.PdfImageType.Bitmap, 300, 300);
FileUtil.BytesToFile(ImageHelper.ImageToBytes(image), pdfjpg);
}
//存储一个路径 info.SavePath = pdfjpgPath;//修改使用这个属性返回使用

最后返回对应的Json信息即可

                //序列号返回对象信息
                string result =JsonConvert.SerializeObject(info, Formatting.Indented);return Content(result);

我们在页面视图中,通过ajax请求处理即可实现图片的动态显示了。

        //刷新列表
    var ID = '';functionRefresh() {var filename = $("#WHC_FileName").val();//获取或生成对应的PDF文件,根据路径显示
        $.getJSON("/PdfView/FindByFileName?r=" + Math.random() + "&name=" + filename, function(info) {if (info != '') {//获取图片路径,设置显示
                $("#imgfapiao").attr("src", info.SavePath);
}
});
}

最后实现了图片的预览展示。

上面就是我的一个解决思路,如果您有更好的方式解决PDF在线预览问题,欢迎彼此交流。

在早期Bootstrap框架介绍中,我的随笔《
结合bootstrap fileinput插件和Bootstrap-table表格插件,实现文件上传、预览、提交的导入Excel数据操作流程
》中介绍了利用Bootstrap FieInput插件上传Excel文件到服务器,然后利用Bootstrap-table表格插件进行展示数据,最后导入到系统里面中,这个导入过程中可以预览到要导入的数据,而且可以选择性的导入。在实际使用过程中,发现使用Ajax导入大批量(几百条记录数据)的情况下,页面就会罢工,估计和提交的数据大小限制有关,为了解决这个问题,并结合导入数据一般都是全部导入的情况下,我们修改下数据导入的过程,从而实现大量数据量的Excel数据导入。

1、使用预览数据,并勾选导入的处理方式

Excel导入的的界面展示如下所示。

上传文件后,数据直接展示在弹出层的列表里面,这里直接使用了 Bootstrap-table表格插件进行展示。

这样我们就可以把Excel的记录展示出来,实现了预览的功能,勾选必要的记录,然后保存即可提交到服务器进行保存,实现了Excel数据的真正导入数据库处理。

实际的代码就比较多一点点,详细可以参考下随笔《
结合bootstrap fileinput插件和Bootstrap-table表格插件,实现文件上传、预览、提交的导入Excel数据操作流程
》,这里就主要简要介绍下导入的处理逻辑即可,由于是在客户端组装列表数据,然后通过ajax提交的,它的的代码如下所示。(这个也就是后面需要解决的问题)。

        //保存导入的数据
        functionSaveImport() {var list = [];//构造集合对象
            var rows = $import.bootstrapTable('getSelections');for (var i = 0; i < rows.length; i++) {
list.push({
'Name': rows[i].Name, 'Mobile': rows[i].Mobile, 'Email': rows[i].Email, 'Homepage': rows[i].Homepage,'Hobby': rows[i].Hobby, 'Gender': rows[i].Gender, 'Age': rows[i].Age, 'BirthDate': rows[i].BirthDate,'Height': rows[i].Height, 'Note': rows[i].Note
});
}
if (list.length == 0) {
showToast(
"请选择一条记录", "warning");return;
}
var postData = { 'list': list };//可以增加其他参数,如{ 'list': list, 'Rucanghao': $("#Rucanghao").val() }; postData =JSON.stringify(postData);

$.ajax({
url:
'/TestUser/SaveExcelData',
type:
'post',
dataType:
'json',
contentType:
'application/json;charset=utf-8',
traditional:
true,
success:
function(data) {if(data.Success) {//保存成功 1.关闭弹出层,2.清空记录显示 3.刷新主列表 showToast("保存成功");

$(
"#import").modal("hide");
$(bodyTag).html(
"");
Refresh();
}
else{
showToast(
"保存失败:" + data.ErrorMessage, "error");
}
},
data: postData
});
}

在实际使用过程中,发现数据几百条的时候,页面就罢工了,不能正常插入,搜索下解决问题说是大小受限的问题,但是我在Web.Config里面也设置了上传文件的大小,最终没有找到配置解决思路。

<httpRuntimeexecutionTimeout="600"maxRequestLength="951200"useFullyQualifiedRedirectUrl="true"minFreeThreads="8"minLocalRequestFreeThreads="4"appRequestQueueLimit="100"enableVersionHeader="true"/> 

最终这个配置项也无法解决,那么我们只能找其他方式来避免数据大量提交了。

2、使用在控制器后台读取Excel文件导入数据库

以上的数据导入方式,在一般数据比较少的时候,体验还是不错的,不过它的过程也是先上传Excel文件,然后读取Excel里面的记录,转换为对应的List<T>类型,在序列号JSON列表在前端界面展示。

既然我们文件在服务器上,并且也可以通过把Excel文件转换为对应的List<T>,那么我们减少用户勾选的步骤,确认后直接读取导入即可,这样处理应该就没有这样的受限于页面数据大小的问题的。

这样我们以设备信息导入为案例,介绍这个处理过程,如下前端代码是在文件上传到服务器后,用户确认后负责导入的逻辑的。

             //保存导入的数据
        functionSaveImport() {var postData = { 'guid': importGuid };
postData
=JSON.stringify(postData);

$.ajax({
url:
'/Device/SaveExcelByGuid',
type:
'post',
dataType:
'json',
contentType:
'application/json;charset=utf-8',
traditional:
true,
success:
function(data) {if(data.Success) {
Refresh();
//保存成功 1.关闭弹出层,2.清空记录显示 3.刷新主列表 showToast("保存成功");

$(
"#import").modal("hide");
$(bodyTag).html(
"");
}
else{
showToast(
"保存失败:" + data.ErrorMessage, "error");
}
},
data: postData
});

最终我们是看到处理方式是在SaveExcelByGuid的控制器方法里面的,这个方法根据服务器的GUID,获取对应Excel文件的信息,然后进行读取和导入操作。

这个方法的详细代码如下所示。

        /// <summary>
        ///在服务端保存Excel/// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public ActionResult SaveExcelByGuid(stringguid)
{
CommonResult result
= newCommonResult();if(!string.IsNullOrEmpty(guid))
{
var list = GetDevice(guid);//根据guid获取对应的Excel文件,并把内容转换为对应的List<T> if (list != null)
{
foreach (DeviceInfo detail inlist)
{
var isExist = BLLFactory<Device>.Instance.IsExistKey("DeviceId", detail.DeviceId);if (!isExist)
{
BLLFactory
<Device>.Instance.Insert(detail);
}
}
//成功操作 result.Success = true;
}
else{
result.ErrorMessage
= "导入信息不能为空";
}
}
else{
result.ErrorMessage
= "导入信息不能为空";
}
returnToJsonContent(result);
}

其中我们看到 GetDevice(guid) 就是获取Excel文件内容并转换为对应的实体类列表过程的。

其中的GetDevice就是转换为对应实体类集合的过程,代码如下所示。

        /// <summary>
        ///获取设备导入文件,转换为对应的实体类集合/// </summary>
        /// <param name="guid">附件GUID</param>
        /// <returns></returns>
        private List<DeviceInfo> GetDevice(stringguid)
{
List
<DeviceInfo> list = new List<DeviceInfo>();

DataTable table
=ConvertExcelFileToTable(guid);if (table != null)
{
#region 数据转换 foreach (DataRow dr intable.Rows)
{
DeviceInfo info
= newDeviceInfo();
info.DeviceId
= dr["设备ID"].ToString();
info.VersionInfo
= dr["版本信息"].ToString();
info.MinitorInfo
= dr["预留监控信息"].ToString();
info.DeviceMsisdn
= dr["公话手机号"].ToString();

list.Add(info);
}
#endregion}returnlist;
}

而 ConvertExcelFileToTable 就是利用aspose.Cell的Excel操作控件,实现数据转换的。

        /// <summary>
        ///从附件列表中获取第一个Excel文件,并转换Excel数据为对应的DataTable返回/// </summary>
        /// <param name="guid">附件的Guid</param>
        /// <returns></returns>
        protected DataTable ConvertExcelFileToTable(stringguid)
{
DataTable dt
= null;if (!string.IsNullOrEmpty(guid))
{
//获取上传附件的路径 string serverRealPath = BLLFactory<FileUpload>.Instance.GetFirstFilePath(guid);if (!string.IsNullOrEmpty(serverRealPath))
{
//转换Excel文件到DatTable里面 string error = "";
dt
= newDataTable();
AsposeExcelTools.ExcelFileToDataTable(serverRealPath,
out dt, outerror);
}
}
returndt;
}

这样实现效果,不考虑用户勾选记录的情况,确认后直接对整个Excel文件进行判断导入操作,一般也是符合我们实际的导入过程的,这样处理起来,再也不会有前面介绍的那种情况了,至少我们能够顺利上传Excel文件,在后台读取Excel文件并转换是没有什么压力的,而且体验效果也很不错,非常快速。

最后看看大量数据导入后,也能够快速刷新,并能够在分页控件进行展示了。