excel表格导入功能

1、表格导入方法

(1)首先jsp文件中加入对应的HTML样式,并调用对应js中的方法

 <em class="separ"></em>
            <a class="txt-all" onclick="pageObj.import()"><i class="iconfont icon-up"></i>导入</a>
            <em class="separ"></em>
            <a class="txt-all" onclick="ExcelUtil.export('${pageTitle}.xls', pageObj.getDataGrid())">
                <i class="iconfont icon-down"></i>导出</a>
            <em class="separ"></em>


//这是设置点击导入按钮弹出的弹框的表单和对应方法
    <div class="invisible">
        <iframe id="importIframe" name="importIframe"></iframe>
        <form id="importForm" target="importIframe" method="post" enctype="multipart/form-data"
              action="${staticContextPath}/import/importExcel.json">
            <input type="file" name="importFile" id="importFile"
                   onchange="window.pageObj.importForm()" accept=".xls,.xlsx"/>
            <input type="hidden" name="type" value="publishLicense"/>
            <input type="hidden" name="pageObj" value="pageObj"/>
            <input type="hidden" name="dataGridMethod" value="getDataGrid"/>
        </form>
    </div>

(2)js文件中代码段

getDataGrid: function () {
            var $grid = $("#grid");
            if (!$grid[0].grid) {
                $grid.jqGrid({
                    url: App["contextPath"] + "/bs/publishLicense/getPublishLicensePage.json",
                    ajaxGridOptions: {
                        contentType: "application/json"
                    },
                    autoWidthPadding: 25,
                    autoHeightPadding: 90,
                    shrinkToFit: true,//自适应都挤在一块
                    multiselect: false,
                    multiboxonly: false,
                    enabledLoad: false,
                    pager: "#pager",
                    colModel: [
                        {name: "id",label: "主键",hidden: true},
                        {
                            name: "operate", label: "操作", width: 80, align: 'center',
                            formatter: function (cellContent, options, rowData) {
                                var html = '';
                                html += "<a class='mr5' οnclick='pageObj.edit(\"" + rowData.id + "\")'>编辑</a>";
                                html += "<a class='mr5' οnclick='pageObj.delete(this, \"" + rowData.id + "\")'>删除</a>";
                                return html;
                            }
                        },
                        {name:'name', label:'出版公司名称',align:'center'},
                        {name: 'publishLicense', label:'经营许可证',align:'center'},
                        {name:'phone', label:'手机号码', align:'center'}
                    ]
                });
            }
            return $grid;
        },
        import: function () {
            var fileObj = document.getElementById('importFile');
            fileObj.value = ''; // 每次先将file值设置为空值
            fileObj.click();
        },
        importForm: function () {
            document.getElementById('importForm').submit();
            $('body').block({
                message: '<h1>正在导入,请稍候...</h1>',
                css: {
                    width: '',
                    left: '40%',
                    border: 'none',
                    padding: '15px',
                    backgroundColor: '#000',
                    '-webkit-border-radius': '10px',
                    '-moz-border-radius': '10px',
                    opacity: .5,
                    color: '#fff'
                },
                overlayCSS: {backgroundColor: '#000', opacity: 0.4}
            });
        },
    });

第二步注意的几点:1、getDataGrid方法中

var $grid = $("#grid");
 pager: "#pager",

两个属性的绿色的值要与jsp中的值对应

2、import和importForm 方法中绿色的值和jsp中相应字段值对应

import: function () {
    var fileObj = document.getElementById('importFile');
    
importForm: function () {
    document.getElementById('importForm').submit();

这次用AbstractImportHandler抽象类先封装导入方法和获取excel表格中行列值的方法

public abstract class AbstractImportHandler {


    protected Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 导入
     *
     * @param sheet 工作簿
     * @param user  user
     * @return 错误消息
     */
    public abstract String doHandler(Sheet sheet, UserVOExt user);

    protected String getCell(Row row, int colIdx, String errMsg) {
        return Optional.ofNullable(getCellValue(row.getCell(colIdx))).orElseThrow(() -> new BusinessException(errMsg));
    }

    protected String getCellValue(Cell cell) {
        String cellValue = null;

        if (cell != null){
            if (CellType.STRING == cell.getCellTypeEnum()) {
                cellValue = cell.getStringCellValue();
            }
//            else (CellType.NUMERIC == cell.getCellTypeEnum()){
//                cellValue = cell.getNumericCellValue();
//            }
        }
        return cellValue;
    }

}

在具体实现类中重写doHandler方法

@Component
@ImportHandler(type = "publishLicense")
public class PublishLicenseImportHandler extends AbstractImportHandler {

    /**
     * 书店索引值
     */
    private final static Integer  STORE_NAME = 0;
    /**
     * 出版物经营许可证索引值
     */
    private final static Integer  PLNUM_INDEX = 1;
    /**
     * 手机号索引值
     */
    private final static Integer  PHONE_INDEX = 2;

    @Autowired
    private IPublishLicenseService publishLicenseService;

    @Override
    public String doHandler(Sheet sheet, UserVOExt user) {
        // 校验数据,存储数据,报错信息
        //Set<String> corpSet = new HashSet<>(); Set<String> cdrSet = new HashSet<>();
        List<String> plNumList = new ArrayList<>();
        List<String> phoneList = new ArrayList<>();
        List<PublishLicenseVOExt> records = new ArrayList<>();
        String errorMessage = "";
        //0行是标题 从第一行开始
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            try{
                Row row = sheet.getRow(i);
                String storeName = getCell(row, STORE_NAME, "书店名称不能为空");
                String publishLicense = getCell(row, PLNUM_INDEX, "出版物经营许可证不能为空");
                String phone = convertCellValueToString(row.getCell(PHONE_INDEX),row);
                PublishLicenseVOExt voExt = new PublishLicenseVOExt();
                voExt.setName(storeName);
                voExt.setPublishLicense(publishLicense);
                voExt.setPhone(phone);
                publishLicenseService.checkPublishLicense(publishLicense, phone);
                records.add(voExt);
            }catch (BusinessException e){
                e.printStackTrace();
                errorMessage = String.format("导入失败!第%d行: %s", i+1, e.getMessage());
                break;
            }
        }
        publishLicenseService.saveImport(records);
        return errorMessage;
    }
    private String convertCellValueToString(Cell cell, Row row) {
        return new DecimalFormat("#").format(cell.getNumericCellValue());
    }

}

特别说明该类 @ImportHandler(type = “publishLicense”)注解中type的值要与jsp文件中相应属性的值一定要一样,因为这里属于映射关系

(3)编写导入功能的接口

@Controller
@RequestMapping("/import")
public class ImportController extends BaseController {

    private final static String IMPORTS_PACKAGE_PATH = "com.jiujie.book.application.web.imports";

    /**
     * Excel载入公共入口
     *
     * @param file     导入文件
     * @param request  请求参数
     * @param response 响应参数
     * @throws IOException 异常
     */
    @RequestMapping(value = "/importExcel.json", method = RequestMethod.POST)
    public void importExcel(@RequestParam("importFile") MultipartFile file, HttpServletRequest request,
                            HttpServletResponse response) throws IOException {
        String type = request.getParameter("type");
        String pageObj = request.getParameter("pageObj");
        String dataGridMethod = request.getParameter("dataGridMethod");
        PrintWriter out = response.getWriter();
        if (!file.isEmpty()) {
            try {
                POIFSFileSystem fs = new POIFSFileSystem(file.getInputStream());
                HSSFWorkbook wb = new HSSFWorkbook(fs);
                Sheet sheet = wb.getSheetAt(0);
                String errorMessage = importRoute(type, sheet);

                if ("".equals(errorMessage)) {
                    out.println("<script>parent.TipsUtil.info('载入成功!');parent." + pageObj + "." + dataGridMethod + "().jqGrid('reloadGrid');parent.$('body').unblock();</script>");
                } else {
                    out.println("<script>parent.TipsUtil.error('" + errorMessage + "');parent.$('body').unblock();</script>");
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                if (StringUtils.isNotEmpty(e.getMessage()) && e.getMessage().contains("Your file appears not to be a valid OLE2 document")) {
                    out.println("<script>parent.TipsUtil.error('请使用标准导入模板来导入数据!');</script>");
                } else if (StringUtils.isNotEmpty(e.getMessage()) && e.getMessage().contains("The supplied data appears to be in the Office 2007+ XML")) {
                    out.println("<script>parent.TipsUtil.error('请使用下载的模版添加数据进行导入!');</script>");
                } else {
                    out.println("<script>parent.TipsUtil.error('导入的模板有误,请校验是否满足以下要求:<br/>" +
                            "'1、填写的单元格中不得包含计算公式;<br/>'+\n" +
                            "'2、导入的模板不能删除或添加列;<br/>'+\n" +
                            "'3、需要下拉选择的信息,只能是模板中的选择项。');</script>");
                }
            } finally {
                out.close();
            }
        }
    }

    /**
     * 导入处理类路由,通过模板类型映射到对应的处理类
     *
     * @param type  模板类型
     * @param sheet 导入文件Excel
     * @return 错误消息
     * @throws ClassNotFoundException 类未找到
     */
    private String importRoute(String type, Sheet sheet) throws ClassNotFoundException {
        AbstractImportHandler bean = (AbstractImportHandler) SpringContextUtil.getBean(getImportHandlerClass(type));
        return bean.doHandler(sheet, getCurrentUser());
    }

    /**
     * 遍历imports目录下,先匹配注解ImportHandler type的值
     * 如果没有再匹配类名,如:ImportClazzHandler
     *
     * @param type 导入文件类型
     * @return 类
     * @throws ClassNotFoundException 类未找到
     */
    private Class<?> getImportHandlerClass(String type) throws ClassNotFoundException {
        ConfigurationBuilder builder = new ConfigurationBuilder();
        builder.setUrls(ClasspathHelper.forPackage(IMPORTS_PACKAGE_PATH));
        builder.filterInputsBy(new FilterBuilder().include(IMPORTS_PACKAGE_PATH + ".*.class"));
        Set<Class<?>> classList = new Reflections(builder).getTypesAnnotatedWith(ImportHandler.class);

        for (Class<?> clazz : classList) {
            ImportHandler importHandler = clazz.getAnnotation(ImportHandler.class);
            if (importHandler.type().equals(type)) {
                return clazz;
            }
        }

        String className = "Import" + StringUtils.capitalize(type) + "Handler";
        return Class.forName(IMPORTS_PACKAGE_PATH + "." + className);
    }

}

通过流来读取文件,在调用importRoute方法,遍历文件的行列数据,第三个方法是用来确定上传文件和对应handler映射关系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值