Dynamic CRM 2013学习笔记(三十一)自定义用excel批量导入实体数据
有一个实体的子表数据量太大,于是客户想用execel来导入实体数据。首先想到的是用系统自带的Import Data,客户嫌太麻烦,比如lookup字段要做map等。
下面是具体的实现步骤:
一、定义excel数据模板
1. 利用系统自带的Download Template For Import下载系统自带的模板
2. 去掉不需要的列,比如有些列是自动计算,自动赋值
3. 保存为excel文件,并copy到crm server里的isv目录下
4. 定义一个按钮,并指定调用下面的js:
// export purchase detail template
function downloadDetailTemplate() {
var url = "/ISV/TempDownLoad/OrderDetail.xls";
var hiddenIFrameID = 'hiddenDownloader',
iframe = document.getElementById(hiddenIFrameID);
if (iframe === null) {
iframe = document.createElement('iframe');
iframe.id = hiddenIFrameID;
iframe.style.display = 'none';
document.body.appendChild(iframe);
}
iframe.src = url;
}
二、导入数据
1. 在上面定义的excel模板里填充数据
2. 定义一个aspx页面:
<div style="margin-top: 20px; margin-left: 10px">
<asp:FileUpload ID="FileUpload1" runat="server" Height="20px" />
<asp:Button ID="btSubmit" runat="server" Text="上传" OnClientClick="javascript:return extension();"
OnClick="btSubmit_Click" Height="20px" />
<br />
<br />
<asp:Label ID="lbMessage" runat="server" Text=""></asp:Label>
</div>
很简单,一个上传控件,一个上传按钮
3. 为这个实体建一个类,跟excel里的列一一对应
public class PurchaseOrderDetails
{
//public string OrderNo { get; set; }
public string PartNo { get; set; }
public decimal Quantity { get; set; }
public decimal UnitPrice { get; set; }
public string Remarks { get; set; }
public string CorrespondingSONo { get; set; }
public decimal SWAPRate { get; set; }
public DateTime RequestedDeliveryDate { get; set; }
public string Model { get; set; }
public string Description { get; set; }
public decimal SOQuantity { get; set; }
}
4. 读取excel里的数据,并转换成上面定义的类
System.IO.FileInfo fileinfo = new System.IO.FileInfo(FileUpload1.PostedFile.FileName);
int fileLen = FileUpload1.PostedFile.ContentLength;
Byte[] FileData = new Byte[fileLen];
HttpPostedFile hps = FileUpload1.PostedFile;
System.IO.Stream stream = hps.InputStream;
stream.Read(FileData, 0, fileLen);
ExcelDataReader.ExcelDataReader spreadsheet = new ExcelDataReader.ExcelDataReader(stream);
if (spreadsheet.WorkbookData.Tables.Count == 0)
{
throw new Exception("File loading error!");
}
DataTable dt = spreadsheet.WorkbookData.Tables[0];
int filecount = dt.Columns.Count;
PurchaseOrderDetails detail = new PurchaseOrderDetails();
Type type = detail.GetType();
PropertyInfo[] propertyInfos = type.GetProperties();
if (propertyInfos.Length != filecount)
{
throw new Exception("File Template is not correct!");
}
List<PurchaseOrderDetails> detailList = new List<PurchaseOrderDetails>();
for (int index = 1; index < dt.Rows.Count - 1; index++)
{
detail = new PurchaseOrderDetails();
int count = 0;
int nullcount = 0;//判断是否空数据
foreach (PropertyInfo property in propertyInfos)
{
string csvvalue = dt.Rows[index][count].ToString();
if (csvvalue != null && csvvalue != "")
{
csvvalue = ToDBC(csvvalue);
object convertValue = null;
try
{
convertValue = Convert.ChangeType(csvvalue, property.PropertyType);
}
catch (Exception ex)
{
property.SetValue(detail, convertValue, null);
count++;
continue;
}
property.SetValue(detail, convertValue, null);
}
else
{
property.SetValue(detail, null, null);
nullcount++;
}
count++;
}
if (nullcount == propertyInfos.Length)
{
continue;
}
detailList.Add(detail);
}
spreadsheet.WorkbookData.Dispose();
stream.Close();
5. 验证,转换成真实的实体
Entity orderDetail = new Entity("new_purchase_details");
// 0. order no
orderDetail["new_purchaseid"] = new EntityReference("new_purchase", Guid.Parse( entityId));
// 1. part no
var ents = getData("new_product", "new_name", item.PartNo.Trim());
Guid productid;
if (ents.Entities.Count == 0)
{
throw new Exception(string.Format("Part No (row {0}) is wrong !", i + 1));
}
else
{
productid = ents.Entities[0].Id;
orderDetail["new_productid"] = new EntityReference("new_product", productid);
}
// 2. model
ents = getData("new_model", "new_name", item.Model.Trim());
if (ents.Entities.Count == 0)
{
throw new Exception(string.Format("Model (row {0}) is wrong !", i + 1));
}
else
{
orderDetail["new_model"] = new EntityReference("new_model", ents.Entities[0].Id);
}
// 3. Quantity
orderDetail["new_request_quantity"] = item.Quantity;
// 4. Description
orderDetail["new_description"] = item.Description;
// 5. Unit Price
orderDetail["new_unit_price"] = item.UnitPrice;
// 6. Amount
orderDetail["new_amount"] = item.Quantity * item.UnitPrice;
using (OrganizationServiceContext orgContext = new OrganizationServiceContext(m_CrmService))
{
foreach (Entity item in entityList)
{
orgContext.AddObject(item);
}
orgContext.SaveChanges();
}
6. 发布这个页面,并在实体上加上按钮,调用下面的js
var openURL = "http://12.2.3/ImportOrderDetail.aspx?entityId=";
window.open(openURL + Xrm.Page.data.entity.getId().toString(), "_blank", "dialogWidth=800px;dialogHeight=400px;help:no;status:no");
这里要把主实体的id带过去, 因为插入子实体时要用到,否保存时会报下面的错误:
Exception has been thrown by the target of an invocation
Dynamic CRM 2013学习笔记 系列汇总 -- 持续更新中
Dynamic CRM 2013学习笔记(三十一)自定义用excel批量导入实体数据的更多相关文章
- Dynamic CRM 2013学习笔记(十一)利用Javascript实现子表合计(汇总,求和)功能
我们经常有这样一种需求,子表里新加或修改一数值后,要马上在主表里把它们的和显示在主表上.如果用插件来实现,可以实现求和,但页面上还要刷新一下才能显示正确.这时就考虑到用JS来实现这一功能,并自动刷新页 ...
- Dynamic CRM 2013学习笔记 系列汇总
这里列出所有 Dynamic CRM 2013学习笔记 系列文章,方便大家查阅.有任何建议.意见.需要,欢迎大家提交评论一起讨论. 本文原文地址: Dynamic CRM 2013学习笔记 系列汇总 ...
- Dynamic CRM 2013学习笔记(十二)实现子表合计(汇总,求和)功能的通用插件
上一篇 Dynamic CRM 2013学习笔记(十一)利用Javascript实现子表合计(汇总,求和)功能 , 介绍了如何用js来实现子表合计功能,这种方法要求在各个表单上添加js方法,如果有很多 ...
- Dynamic CRM 2013学习笔记(三十二)自定义审批流3 - 节点及实体配置
上次介绍了<Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示> 以及如何配置自定义审批流的按钮:<Dynamic CRM 2013学习笔记(二十一)自定义 ...
- Dynamic CRM 2013学习笔记(三十七)自定义审批流7 - 初始化(整套审批流下载、安装)
前面介绍了自定义审批流的配置.使用,这篇介绍下如何进行初始化. 一. 下载 从下面的地址下载整个审批流: http://yunpan.cn/cZ5Rdx5HCt3VF 下载完后,一共有三块内容: 二. ...
- Dynamic CRM 2013学习笔记(二十一)自定义审批流2 - 配置按钮
上次介绍了 Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示 现在开始介绍如何配置审批流,首先在form上添加三个按钮,Submit, Agree, Reject: 1. ...
- Dynamic CRM 2013学习笔记(三十三)自定义审批流4 - 规则节点 -有分支的流程处理
上次介绍过节点的基本配置<Dynamic CRM 2013学习笔记(三十二)自定义审批流3 - 节点及实体配置>,这次介绍下规则节点,因为有时流程里会有一些分支.合并,这时就要用到规则节点 ...
- Dynamic CRM 2013学习笔记(三十五)自定义审批流6 - 审批通过后,再审批 - 二次审批
最近有个特殊的需求,客户想做二次审批,就是审批通过后,再走一次审批流程.最开始一想,这还不简单,审批通过后,直接把状态改成draft就完了,后来一试,发现一堆问题,比如第一次审批完后,界面是不允许修改 ...
- Dynamic CRM 2013学习笔记(三十四)自定义审批流5 - 自动邮件通知
审批过程中,经常要求自动发邮件:审批中要通知下一个审批人进行审批:审批完通知申请人已审批完:被拒绝后,要通知已批准的人和申请人.下面详细介绍如何实现一个自动发邮件的插件: 1. 根据审批状态来确定 ...
随机推荐
- 阿里巴巴分布式服务框架Dubbo介绍(1)主要特色
引言 互联网服务和BS架构的传统企业软件相比,系统规模上产生了量级的差距.例如 传统BS企业内部门户只需要考虑数百人以及几千人的访问压力,而大型互联网服务有时需要考虑的是千万甚至上亿的用户: 传统企业 ...
- mongodb下载、安装、配置服务启动、及可视化工具下载、使用
MongoDB: 1.下载地址:http://www.mongodb.org/downloads(32位还是64位自行选择).我下载的是:mongodb-win32-x86_64-3.2.4-sign ...
- FTP\TFTP
FTP是文件传输协议的英文简写. FTP 文件传输协议 基于TCP,20和21端口. TFTP 简单文件传输协议,基于UDP,69 只能传输32Mb以下文件,不需要提供账号和密码.tftp xxx.x ...
- Jsoncpp的使用
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器解析和生成. 它基于JavaScript Programming Lan ...
- gdb调式
1.PCB版的相应目录下执行命令: gdbserver 10.18.13.84:5555 DvdPlayer 2.linux操作系统执行:(如果是android找到android项目路径下的gdb)m ...
- cms替换主页的步骤
cms替换主页的步骤 .先做好静态页面: .在D:\wamp\www\phpcms\install_package\phpcms\templates文件夹下建新的文件夹tianqiwangluo(项目 ...
- 初识ASP.NET CORE:一、HTTP pipeline
完整的http请求在asp.net framework中的处理流程: Asp.Net HttpRequest--> HTTP.exe--> inetinfo.exe(w3wp.exe)-& ...
- Scrum会议(Beta版本)
组名:天天向上 组长:王森 组员:张政.张金生.林莉.胡丽娜 代码地址:HTTPS:https://git.coding.net/jx8zjs/llk.git SSH:git@git.coding.n ...
- ArcGIS删除部分数据后全图范围不正确
我有一个全国地图的图层,现在删除图层中其他省份,只保留山东省的图形,但是点击全图后,全图范围仍然是全国地图时候的全图范围,使用的版本是ArcGIS9.3,数据存放在9.3的个人数据库中(Perso ...
- 在UITableViewStylePlain情况下sectionHeader可以与tableview一起滑动的解决方法
-(void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat sectionHeaderHeight = ; ) { scrollVi ...