动态级联下拉模板导出

  • 前言
    • 一、构建项目结构
    • 二、最终效果(下载到本地,流的形式可自行测试)
    • 三、具体实现
      • 1)pom.xml 依赖
      • 2)注解类 Excel 和 ExcelFile
      • 3)构建实体类 TestTemplate ,添加注解
      • 4)构建数据获取类 ExcelDataService
      • 5)构建工具类 ExcelUtils
      • 6)反射类 ReflectionUtil
      • 7) 最后写个测试类测试

前言

在项目中需要动态的生成带级联下拉的excel模板,数据来源为mysql数据库,因为不需要产生过程中的临时文件,所有楼主是使用了直接返回前端文件流的形式。
本文提供了

1、直接返回流的形式
2、生成本地文件之后返回文件路径

注:因为是基于excel的名称管理器和poi实现,在poi设置名称管理器的名字存在字符验证。如下的验证,所以对于作为下拉的数据有相应的要求。必须是汉字、数字、字母、下划线和点且不能是数字和点开头。

 private static void validateName(String name) {if (name.length() == 0) {throw new IllegalArgumentException("Name cannot be blank");}if (name.length() > 255) {throw new IllegalArgumentException("Invalid name: '"+name+"': cannot exceed 255 characters in length");}if (name.equalsIgnoreCase("R") || name.equalsIgnoreCase("C")) {throw new IllegalArgumentException("Invalid name: '"+name+"': cannot be special shorthand R or C");}// is first character valid?char c = name.charAt(0);String allowedSymbols = "_\\";boolean characterIsValid = (Character.isLetter(c) || allowedSymbols.indexOf(c) != -1);if (!characterIsValid) {throw new IllegalArgumentException("Invalid name: '"+name+"': first character must be underscore or a letter");}// are all other characters valid?allowedSymbols = "_.\\"; //backslashes needed for unicode escapefor (final char ch : name.toCharArray()) {characterIsValid = (Character.isLetterOrDigit(ch) || allowedSymbols.indexOf(ch) != -1);if (!characterIsValid) {throw new IllegalArgumentException("Invalid name: '"+name+"': name must be letter, digit, period, or underscore");}}// Is the name a valid $A$1 cell reference// Because $, :, and ! are disallowed characters, A1-style references become just a letter-number combinationif (name.matches("[A-Za-z]+\\d+")) {String col = name.replaceAll("\\d", "");String row = name.replaceAll("[A-Za-z]", "");try {if (CellReference.cellReferenceIsWithinRange(col, row, SpreadsheetVersion.EXCEL2007)) {throw new IllegalArgumentException("Invalid name: '"+name+"': cannot be $A$1-style cell reference");}} catch (final NumberFormatException e) {// row was not parseable as an Integer, such as a BigInt// therefore name passes the not-a-cell-reference criteria}}// Is the name a valid R1C1 cell reference?if (name.matches("[Rr]\\d+[Cc]\\d+")) {throw new IllegalArgumentException("Invalid name: '"+name+"': cannot be R1C1-style cell reference");}}

一、构建项目结构

二、最终效果(下载到本地,流的形式可自行测试)



三、具体实现

1)pom.xml 依赖

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.gongl</groupId><artifactId>poi-select</artifactId><version>1.0</version><name>poi-select</name><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencies><!-- SpringBoot的依赖配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.5.8</version><type>pom</type><scope>import</scope></dependency><!-- excel工具 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.1.2</version></dependency><!-- servlet包 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><!-- log4j日志组件 --><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.17.1</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-to-slf4j</artifactId><version>2.17.1</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.9</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency></dependencies>
</project>

2)注解类 Excel 和 ExcelFile

package com.gongl.annotation;import org.apache.poi.ss.usermodel.DataValidationConstraint;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author gongl* @date 2022-08-16*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Excel {/*** 列名*/String name() default "";int columnWidth() default (int) ((22 + 0.72) * 256);/*** 排序*/int order();/*** 是否支持动态列*/boolean dynamic() default false;/*** 数据源方法全名*/String datasourceMethod() default "";/*** 前列字段* 当为空字符串时,认定无前列依赖*/String beforeFieldName() default "";/*** 开始行*/int firstRow() default 2;/*** 结束行*/int lastRow() default 200;/*** 校验类型*/int validationType() default DataValidationConstraint.ValidationType.LIST;}
package com.gongl.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/**
* @author gongl
* @date 2022-08-16
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelFile {/*** 文件全名*/String fileName() default "excel.xlsx";/*** 页名称*/String sheetName() default "sheet1";/*** 为true时,创建数据页,当不存在级联下拉时可设置为不创建*/boolean enableDataValidation() default false;/*** 数据页名称*/String dataSheetName() default "dataSheet";/*** 隐藏数据页*/boolean datasheetHidden() default true;}

3)构建实体类 TestTemplate ,添加注解

package com.gongl.base;import com.gongl.annotation.Excel;
import com.gongl.annotation.ExcelFile;/*** @author gongl* @date 2022-08-16*/
@ExcelFile(enableDataValidation = true, fileName = "测试级联下拉excel.xlsx")
public class TestTemplate {@Excel(name = "姓名", order = 0)private String username;@Excel(name = "所属省", order = 1, datasourceMethod = "com.gongl.service.ExcelDataService.getProvinceList")private String province;@Excel(name = "所属市", order = 2, datasourceMethod = "com.gongl.service.ExcelDataService.getCityList",beforeFieldName = "province")private String city;@Excel(name = "性别", order = 3, datasourceMethod = "com.gongl.service.ExcelDataService.getSexList")private String sex;@Excel(name = "年龄", order = 4)private Integer age;public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}
}

4)构建数据获取类 ExcelDataService

package com.gongl.service;import java.util.*;/*** @author gongl* @date 2022-08-16*/
public class ExcelDataService {//实际开发中,可通过查询数据库获取数据public List<String> getProvinceList(Map<String, Object> map) {return Arrays.asList("四川省","广东省");}public Map<String, List<String>> getCityList(Map<String, Object> map) {Map<String, List<String>> map1 = new HashMap<>();map1.put("四川省",Arrays.asList("南充市","眉山市","成都市"));map1.put("广东省",Arrays.asList("惠州市","中山市","广州市"));return map1;}public  List<String> getSexList(Map<String, Object> map) {return Arrays.asList("男","女","未知");}
}

5)构建工具类 ExcelUtils

package com.gongl.utils;import com.gongl.annotation.Excel;
import com.gongl.annotation.ExcelFile;
import com.gongl.service.ExcelDataService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFDataValidationConstraint;
import org.apache.poi.xssf.usermodel.XSSFDataValidationHelper;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;/*** @author gongl* @date 2022-08-16*/
public class ExcelUtils {private static final Logger log = LoggerFactory.getLogger(ExcelUtils.class);/*** 样式列表*/private static Map<String, CellStyle> styles;//直接下载文件到本地public static void createExcel(Object object, String title, Map<String, Boolean> dynamicMap, Map<String, Object> params) throws IOException {createExcel(null, object, title, dynamicMap, params);}/***  直接返回文件流到前端* @param response* @param object 实体对象* @param title 文件表标题* @param dynamicMap 需要动态展示的数据* @param params 接口的参数* @throws IOException*/public static void createExcel(HttpServletResponse response, Object object, String title, Map<String, Boolean> dynamicMap, Map<String, Object> params) throws IOException {// 取到模板上的所有对象属性Class<?> clazz = object.getClass();List<Field> tempFields = new ArrayList<>();tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));//得到所有的字段名和模板名List<NameMapping> list = new ArrayList<>(16);//得到当前需要导出的列注解for (Field field : tempFields) {if (field.isAnnotationPresent(Excel.class)) {Excel attr = field.getAnnotation(Excel.class);if (attr != null) {field.setAccessible(true);if (null != dynamicMap) {Boolean bl = dynamicMap.get(field.getName());if (attr.dynamic() && bl != null && !bl) {//支持动态,且为动态continue;}}list.add(new NameMapping(field.getName(), attr));}}}//将数据按order升序list = list.stream().sorted(Comparator.comparing(x -> x.getExcel().order())).collect(Collectors.toList());//所有的参数顺序List<String> fieldList = list.stream().map(NameMapping::getFieldName).collect(Collectors.toList());//方法的参数if (params == null) {params = new HashMap<>(1);}boolean annotationPresent = clazz.isAnnotationPresent(ExcelFile.class);if (!annotationPresent) {throw new RuntimeException("不存在ExcelFile注解,不能生成Excel!");}ExcelFile excelFile = clazz.getAnnotation(ExcelFile.class);// 创建excelWorkbook workbook = WorkbookFactory.create(true);// 创建excel页Sheet sheet = workbook.createSheet(excelFile.sheetName());// 创建数据页Sheet dataSheet = null;if (excelFile.enableDataValidation()) {// 创建数据页dataSheet = workbook.createSheet(excelFile.dataSheetName());// 设置隐藏属性workbook.setSheetHidden(workbook.getSheetIndex(dataSheet), excelFile.datasheetHidden());}Map<String, Field> fieldMap = ReflectionUtil.getFieldMap(object);int rowIndex = 0, colIndex = 0;styles = createStyles(workbook);//标题Row titleRow = sheet.createRow(rowIndex);titleRow.setHeightInPoints(50);Cell titleCell = titleRow.createCell(0);titleCell.setCellValue(title);titleCell.setCellStyle(styles.get("title"));sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), list.size() - 1));++rowIndex;//创建表头和下拉for (NameMapping nameMapping : list) {String fieldName = nameMapping.getFieldName();Excel excel = nameMapping.getExcel();sheet.setColumnWidth(colIndex, excel.columnWidth());//创建级联的下拉if (excelFile.enableDataValidation()) {createColumnValidation(fieldList, excel, fieldMap.get(fieldName), workbook, sheet, dataSheet, colIndex, params);}//创建表头createCell(0, sheet, rowIndex, colIndex++, excel.name());}if (null != response) {response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");response.setHeader("Content-Disposition", "attachment;filename=" + new String(URLEncoder.encode(excelFile.fileName(), "utf-8")));response.setHeader("Access-Control-Allow-Origin", "*");try {workbook.write(response.getOutputStream());} catch (Exception e) {log.error("导出Excel异常{}", e.getMessage());} finally {IOUtils.closeQuietly(workbook);}} else {//若需要生成指定文件路径,在这里自定义即可FileOutputStream out = new FileOutputStream(excelFile.fileName());workbook.write(out);out.close();}}private static void createColumnValidation(List<String> fieldList, Excel value, Field field, Workbook workbook, Sheet sheet, Sheet dataSheet, int colIndex,Map<String, Object> params) {if (field == null || dataSheet == null) {return;}field.setAccessible(true);String datasourceMethod = value.datasourceMethod();if ("".equals(datasourceMethod)) {return;}Object invoke;try {invoke = ReflectionUtil.getMethod(datasourceMethod, new ExcelDataService(), params);} catch (IllegalAccessException | InvocationTargetException e) {e.printStackTrace();return;}String formulaIndirectFormat = "=INDIRECT(%s!$%s$%s)";// 判断是否有前置字段if (StringUtils.isBlank(value.beforeFieldName())) {if (!(invoke instanceof Collection)) {return;}Collection collection = (Collection) invoke;//创建下拉的名称管理器int nameManage = createNameManage(workbook, dataSheet, field.getName(), collection);String formulaIndirect = String.format(formulaIndirectFormat, dataSheet.getSheetName(), getCellColumnFlag(1), nameManage + 1);createDataValidate(sheet, formulaIndirect, value.validationType(), value.firstRow(), value.lastRow(), colIndex, colIndex);} else {if (!(invoke instanceof Map)) {return;}Map<String, Collection> map = (Map<String, Collection>) invoke;map.forEach((k, v) -> createNameManage(workbook, dataSheet, k, v));//得到前置字段在第几列int beforeColIndex = 0;for (int i = 0; i < fieldList.size(); i++) {if (fieldList.get(i).equals(value.beforeFieldName())) {beforeColIndex = i;break;}}for (int rowIndex = value.firstRow(); rowIndex <= value.lastRow(); rowIndex++) {String formulaIndirect = String.format(formulaIndirectFormat, sheet.getSheetName(), getCellColumnFlag(beforeColIndex + 1), rowIndex + 1);createDataValidate(sheet, formulaIndirect, value.validationType(), rowIndex, rowIndex, colIndex, colIndex);}}}private static void createDataValidate(Sheet sheet, String formula, int validationType, int firstRow, int lastRow, int firstCol, int lastCol) {CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);XSSFDataValidationHelper xssfDataValidationHelper = new XSSFDataValidationHelper((XSSFSheet) sheet);XSSFDataValidationConstraint xssfDataValidationConstraint = new XSSFDataValidationConstraint(validationType, formula);DataValidation validation = xssfDataValidationHelper.createValidation(xssfDataValidationConstraint, cellRangeAddressList);validation.createErrorBox("输入有误!", "请选择下拉菜单里面的选项!");validation.setEmptyCellAllowed(false);validation.setShowErrorBox(true);sheet.addValidationData(validation);}private static int createNameManage(Workbook workbook, Sheet sheet, String nameString, Collection data) {//数据在第几行final int size = workbook.getAllNames().size();int columnIndex = 0;String format = "%s!$%s$%s:$%s$%s";Name name = workbook.createName();name.setNameName(nameString);String cellColumnFlag = getCellColumnFlag(columnIndex + 2);int nameManageRegan = CollectionUtils.isEmpty(data) ? 1 : data.size() + 1;String nameManageScope = String.format(format, sheet.getSheetName(), cellColumnFlag, size + 1, getCellColumnFlag(nameManageRegan), size + 1);name.setRefersToFormula(nameManageScope);createCell(1, sheet, size, columnIndex, nameString);if (CollectionUtils.isNotEmpty(data)) {for (Object val : data) {createCell(1, sheet, size, ++columnIndex, String.valueOf(val));}}return size;}private static String getCellColumnFlag(int num) {String colFiled = "";int chuNum = 0;int yuNum = 0;if (num >= 1 && num <= 26) {colFiled = doHandle(num);} else {chuNum = num / 26;yuNum = num % 26;yuNum = yuNum == 0 ? 1 : yuNum;colFiled += doHandle(chuNum);colFiled += doHandle(yuNum);}return colFiled;}private static String doHandle(int num) {return String.valueOf((char) (num + 64));}private static void createCell(int type, Sheet sheet, int rowIndex, int colIndex, Object val) {Row row = sheet.getRow(rowIndex);if (row == null) {row = sheet.createRow(rowIndex);}Cell cell = row.getCell(colIndex);if (cell == null) {cell = row.createCell(colIndex);}if (type == 0) {cell.setCellStyle(styles.get("header"));row.setHeightInPoints(40);}cell.setCellValue(val == null ? "" : val.toString());}private static Map<String, CellStyle> createStyles(Workbook wb) {// 标题Map<String, CellStyle> styles = new HashMap<String, CellStyle>();CellStyle style = wb.createCellStyle();style.setAlignment(HorizontalAlignment.CENTER);style.setVerticalAlignment(VerticalAlignment.CENTER);Font titleFont = wb.createFont();titleFont.setFontName("Arial");titleFont.setFontHeightInPoints((short) 16);titleFont.setBold(true);style.setFont(titleFont);style.setWrapText(true);styles.put("title", style);// 表头style = wb.createCellStyle();style.setAlignment(HorizontalAlignment.CENTER);style.setVerticalAlignment(VerticalAlignment.CENTER);style.setBorderRight(BorderStyle.THIN);style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setBorderLeft(BorderStyle.THIN);style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setBorderTop(BorderStyle.THIN);style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setBorderBottom(BorderStyle.THIN);style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setFillPattern(FillPatternType.SOLID_FOREGROUND);Font headerFont = wb.createFont();headerFont.setFontName("Arial");headerFont.setFontHeightInPoints((short) 10);headerFont.setBold(true);headerFont.setColor(IndexedColors.WHITE.getIndex());style.setFont(headerFont);style.setWrapText(true);//换行styles.put("header", style);return styles;}private static class NameMapping {private String fieldName;private Excel excel;public NameMapping(String fieldName, Excel excel) {this.fieldName = fieldName;this.excel = excel;}public String getFieldName() {return fieldName;}public void setFieldName(String fieldName) {this.fieldName = fieldName;}public Excel getExcel() {return excel;}public void setExcel(Excel excel) {this.excel = excel;}}}

6)反射类 ReflectionUtil

package com.gongl.utils;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @author gongl* @date 2022-08-16*/
public class ReflectionUtil {public static Map<String, Field> getFieldMap(Object object) {Map<String, Field> fieldMap = new ConcurrentHashMap<>();refReflectionField(object, fieldMap);return fieldMap;}private static void refReflectionField(Object object, Map<String, Field> fieldMap) {Field[] fields = object.getClass().getDeclaredFields();for (Field field : fields) {fieldMap.put(field.getName(), field);}Class<?> superclass = object.getClass().getSuperclass();if (superclass != null && !"java.lang.Object".equals(superclass.getName())) {refReflectionField(superclass, fieldMap);}}public static Object getMethod(String methodFullName, Object obj, Map<String, Object> map) throws InvocationTargetException, IllegalAccessException {int lastIndex = methodFullName.lastIndexOf('.');String className = methodFullName.substring(0, lastIndex);String methodName = methodFullName.substring(lastIndex + 1);try {Class<?> clazz = Class.forName(className);Method[] methods = clazz.getMethods();for (Method methodObject : methods) {if (methodObject.getName().equals(methodName)) {return methodObject.invoke(obj, map);}}} catch (ClassNotFoundException e) {e.printStackTrace();}return null;}
}

7) 最后写个测试类测试

package com.gongl;import com.gongl.base.TestTemplate;
import com.gongl.utils.ExcelUtils;
import org.junit.Test;import java.io.IOException;public class AppTest {@Testpublic void test() throws IOException {//测试     //直接下载文件到本地ExcelUtils.createExcel(new TestTemplate(),"测试模板下载",null,null);}}

经过上面一顿操作后,最后呈现的就是步骤2)中的结果了。如果有更好的方式,希望大家指教

java 基于注解实现动态级联下拉excel模板相关推荐

  1. html下拉菜单省对应的市,javascript基于DOM实现省市级联下拉框的方法

    省市级联下拉框 var provs = { "江西省": ["南昌市", "景德镇", "九江", "鹰潭&q ...

  2. java动态生成下拉框,标注信息,HSSFDataValidation和数据有效性等设置

    POI的基础使用 java动态生成下拉框属性,设置下拉框数据有效性 /*** 设置下拉框元素** @param firstRow 起始行* @param endRow 结束行* @param firs ...

  3. 级联下拉框效果,动态加载图片

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  4. java下拉树_参数模板中下拉树级联下拉数据集查询

    背景说明 在参数表单的制作中会遇到各种各样的需求,如为了方便参数的输入,需要将输入框设计成树状:若参数模板中有两个输入框,每个输入框对应的参数有某种关系,前一个输入框输入参数后,后一个输入框自动关联到 ...

  5. excel整列动态联动下拉_在Excel下拉列表中显示多列

    excel整列动态联动下拉 A data validation drop down list in Excel only shows one column of items. See how to s ...

  6. Bootstrap级联下拉菜单,你肯定用得到

    今天我将介绍自定义的bootstrap级联下拉菜单(你肯定用得到),主要应用场合有省市级关联菜单等等,那么就先拿这个例子来讲,当然其他场景的关联菜单也同样适用.说实话,封装好一个通用的组件还是需要花费 ...

  7. 使用EasyExcel导出模板并设置级联下拉及其原理分析

    一.概述 项目中有时会遇到需要导出一个Excel模板,然后在导出的Excel中填充数据,最终再调用接口批量把Excel中的数据导入到数据库当中的需求. 其中级联下拉选择,手机号校验,性别校验等都是比较 ...

  8. ajax 下拉框 保留,Ajax生成select级联下拉框和清空多余选项

    Ajax生成select级联下拉框和清空多余选项 实现效果 function professionType(){ var obj=document.getElementById("下拉框id ...

  9. html5级联菜单,h5级联下拉、分类筛选

    级联下拉列表框这种常见的需求,相信大家都经常遇到,下面两种写法都曾运用在项目,测试是没问题,但代码可能不是最好的,亲如果有更好的建议,请留言给我哦-一起探讨 注:数据若为 省市 数据,可利用省市联动的 ...

最新文章

  1. mnist深度学习入门
  2. Windows 下使用Git管理Github项目
  3. 【剑指offer-Java版】18树的子结构
  4. Android开发之获取常用android设备参数信息
  5. php使用模版开发的实例,PHP-Web应用程序开发:使用模板_php
  6. 裁员之后人手却不够,马斯克和母亲只好亲自上阵帮忙了
  7. matlab低通滤波器库函数代码_Matlab中模拟低通滤波器的函数
  8. Win10升级到最新版本
  9. springboot之idea不合并空包
  10. HT6221发送红外HS0038解码程序
  11. Win10系统打开共享文件提示没有权限使用网络资源怎么处理?
  12. forward() takes 2 positional arguments but 3 were given
  13. ArangoDB自学笔记(万字!!全!!)
  14. ecc6.0 oracle安装,SAP ECC v6.0 SR3 IDES Oracle 10.2.0.2 安装指南
  15. python中strip的用法
  16. CSS3打造磨砂玻璃的背景
  17. python中prompt的意思_selenium+Python(alert 、confirm 、prompt 的处理)
  18. 智能化改造推动企业生产过程更为精准与高效
  19. Js放在head和body中的区别
  20. 用border-image实现QQ气泡聊天窗效果

热门文章

  1. 如何创建一个可执行bat文件
  2. CISCO3640路由器配置参考
  3. 使用Web登录防火墙设备
  4. 每日积累(20161212-day-16)(PHILIPS 272P 显示器webcam ,ubuntu使用)
  5. 腾讯QQ2011Beta4插件管理器(去校…
  6. 五种开源协议的比较(BSD、Apache、GPL、LGPL、MIT)
  7. 揭秘MOS管开关时米勒效应的详情
  8. 物联网仪表ADW300无线通讯灵活安装
  9. 机试指南 cha3 哈夫曼
  10. 魔众文库系统 v2.2.0 常规升级,界面和后台优化