2019独角兽企业重金招聘Python工程师标准>>>

网上有一具用于把excel表格数据导出为google protobuf格式,及生成protobuf协议的工具:https://blog.csdn.net/linshuhe1/article/details/52062969 但做过大型游戏的人都知道,当有大量数据需要配置时,同一个excel表格的数据,可能客户端只需要其中的一些列,服务器需要的又是另一些列。分成两个表来维护的话又增加工作量及出错风险。所以我在前人的基础上,稍微把这个工具改了一下,在excel表增加第一行,用于指定该列客户端(填C)用到还是服务器端用(填S)或者是客户端,服务器都用(填CS)。然后在启动导表脚本xls_deploy_tool.py时通过命令行的第四个参数(可选值为:C,S,CS)来指定导出那些列,例如:

python xls_deploy_tool.py GOODS_INFO xls/goods_info.xls C  #只导出客户端列

python xls_deploy_tool.py GOODS_INFO xls/goods_info.xls S  #只导出服务器端列

-----------工具源码-------------------------------------------------------------------------------------------------------------------------------------------------

#! /usr/bin/env python
#coding=utf-8##
# @file:   xls_deploy_tool.py
# @author: jameyli <lgy AT live DOT com>
# @brief:  xls 配置导表工具# 主要功能:
#     1 配置定义生成,根据excel 自动生成配置的PB定义
#     2 配置数据导入,将配置数据生成PB的序列化后的二进制数据或者文本数据
#
# 说明:
#   1 excel 的前五行用于结构定义, 其余则为数据,第一行取值C-S-CS,分别表示该列数仅是客户端或服务器端,或者两者都有,按第二行区分, 分别解释:
#       required 必有属性
#       optional 可选属性
#           第三行: 属性类型
#           第四行:属性名
#           第五行:注释
#           数据行:属性值
#       repeated 表明下一个属性是repeated,即数组
#           第三行: repeat的最大次数, excel中会重复列出该属性
#           2011-11-29 做了修改 第二行如果是类型定义的话,则表明该列是repeated
#           但是目前只支持整形
#           第四行:无用
#           第五行:注释
#           数据行:实际的重复次数
#       required_struct 必选结构属性
#       optional_struct 可选结构属性
#           第三行:结构元素个数
#           第四行:结构名
#           第五行:在上层结构中的属性名
#           数据行:不用填#    1  | required/optional | repeated  | required_struct/optional_struct   |
#       | ------------------| ---------:| ---------------------------------:|
#    2  | 属性类型          |           | 结构元素个数                      |
#    3  | 属性名            |           | 结构类型名                        |
#    4  | 注释说明          |           | 在上层结构中的属性名              |
#    5  | 属性值            |           |                                   |#
#
# 开始设计的很理想,希望配置定义和配置数据保持一致,使用同一个excel
# 不知道能否实现
#
# 功能基本实现,并验证过可以通过CPP解析 ohye
#
# 2011-06-17 修改:
#   表名sheet_name 使用大写
#   结构定义使用大写加下划线
# 2011-06-20 修改bug:
#   excel命名中存在空格
#   repeated_num = 0 时的情况
# 2011-11-24 添加功能
#   默认值
# 2011-11-29 添加功能
# repeated 第二行如果是类型定义的话,则表明该列是repeated
# 但是目前只支持整形# TODO::
# 1 时间配置人性化
# 2 区分server/client 配置
# 3 repeated 优化
# 4 struct 优化# 依赖:
# 1 protobuf
# 2 xlrd
##import xlrd # for read excel
import sys
import os# TAP的空格数
TAP_BLANK_NUM = 4FIELD_CS_ROW = 0
FIELD_RULE_ROW = 1
# 这一行还表示重复的最大个数,或结构体元素数
FIELD_TYPE_ROW = 2
FIELD_NAME_ROW = 3
FIELD_COMMENT_ROW = 4class LogHelp :"""日志辅助类"""_logger = None_close_imme = True@staticmethoddef set_close_flag(flag):LogHelp._close_imme = flag@staticmethoddef _initlog():import loggingLogHelp._logger = logging.getLogger()logfile = 'tnt_comm_deploy_tool.log'hdlr = logging.FileHandler(logfile)formatter = logging.Formatter('%(asctime)s|%(levelname)s|%(lineno)d|%(funcName)s|%(message)s')hdlr.setFormatter(formatter)LogHelp._logger.addHandler(hdlr)LogHelp._logger.setLevel(logging.NOTSET)# LogHelp._logger.setLevel(logging.WARNING)LogHelp._logger.info("\n\n\n")LogHelp._logger.info("logger is inited!")@staticmethoddef get_logger() :if LogHelp._logger is None :LogHelp._initlog()return LogHelp._logger@staticmethoddef close() :if LogHelp._close_imme:import loggingif LogHelp._logger is None :returnlogging.shutdown()# log macro
LOG_DEBUG=LogHelp.get_logger().debug
LOG_INFO=LogHelp.get_logger().info
LOG_WARN=LogHelp.get_logger().warn
LOG_ERROR=LogHelp.get_logger().errorclass SheetInterpreter:"""通过excel配置生成配置的protobuf定义文件"""def __init__(self, xls_file_path, sheet_name,cs="S"):self._xls_file_path = xls_file_pathself._sheet_name = sheet_nameself._cs = cstry :self._workbook = xlrd.open_workbook(self._xls_file_path)except BaseException, e :print "open xls file(%s) failed!"%(self._xls_file_path)raisetry :self._sheet =self._workbook.sheet_by_name(self._sheet_name)except BaseException, e :print "open sheet(%s) failed!"%(self._sheet_name)# 行数和列数self._row_count = len(self._sheet.col_values(0))self._col_count = len(self._sheet.row_values(0))self._row = 0self._col = 0# 将所有的输出先写到一个list, 最后统一写到文件self._output = []# 排版缩进空格数self._indentation = 0# field number 结构嵌套时使用列表# 新增一个结构,行增一个元素,结构定义完成后弹出self._field_index_list = [1]# 当前行是否输出,避免相同结构重复定义self._is_layout = True# 保存所有结构的名字self._struct_name_list = []self._pb_file_name = "tnt_deploy_" + sheet_name.lower() + ".proto"def Interpreter(self) :"""对外的接口"""LOG_INFO("begin Interpreter, row_count = %d, col_count = %d", self._row_count, self._col_count)self._LayoutFileHeader()self._output.append("package tnt_deploy;\n")self._LayoutStructHead(self._sheet_name)self._IncreaseIndentation()while self._col < self._col_count :self._FieldDefine(0)self._DecreaseIndentation()self._LayoutStructTail()self._LayoutArray()self._Write2File()LogHelp.close()# 将PB转换成py格式try :command = "protoc --python_out=./ " + self._pb_file_nameos.system(command)except BaseException, e :print "protoc failed!"raisedef _FieldDefine(self, repeated_num) :LOG_INFO("row=%d, col=%d, repeated_num=%d", self._row, self._col, repeated_num)field_cs = str(self._sheet.cell_value(FIELD_CS_ROW, self._col))if field_cs.find(self._cs) < 0:self._col +=1returnfield_rule = str(self._sheet.cell_value(FIELD_RULE_ROW, self._col))if field_rule == "required" or field_rule == "optional" :field_type = str(self._sheet.cell_value(FIELD_TYPE_ROW, self._col)).strip()field_name = str(self._sheet.cell_value(FIELD_NAME_ROW, self._col)).strip()field_comment = unicode(self._sheet.cell_value(FIELD_COMMENT_ROW, self._col))LOG_INFO("%s|%s|%s|%s", field_rule, field_type, field_name, field_comment)comment = field_comment.encode("utf-8")self._LayoutComment(comment)if repeated_num >= 1:field_rule = "repeated"self._LayoutOneField(field_rule, field_type, field_name)actual_repeated_num = 1 if (repeated_num == 0) else repeated_numself._col += actual_repeated_numelif field_rule == "repeated" :# 2011-11-29 修改# 若repeated第二行是类型定义,则表示当前字段是repeated,并且数据在单列用分好相隔second_row = str(self._sheet.cell_value(FIELD_TYPE_ROW, self._col)).strip()LOG_DEBUG("repeated|%s", second_row);# exel有可能有小数点if second_row.isdigit() or second_row.find(".") != -1 :# 这里后面一般会是一个结构体repeated_num = int(float(second_row))LOG_INFO("%s|%d", field_rule, repeated_num)self._col += 1self._FieldDefine(repeated_num)else :# 一般是简单的单字段,数值用分号相隔field_type = second_rowfield_name = str(self._sheet.cell_value(FIELD_NAME_ROW, self._col)).strip()field_comment = unicode(self._sheet.cell_value(FIELD_COMMENT_ROW, self._col))LOG_INFO("%s|%s|%s|%s", field_rule, field_type, field_name, field_comment)comment = field_comment.encode("utf-8")self._LayoutComment(comment)self._LayoutOneField(field_rule, field_type, field_name)self._col += 1elif field_rule == "required_struct" or field_rule == "optional_struct":field_num = int(self._sheet.cell_value(FIELD_TYPE_ROW, self._col))struct_name = str(self._sheet.cell_value(FIELD_NAME_ROW, self._col)).strip()field_name = str(self._sheet.cell_value(FIELD_COMMENT_ROW, self._col)).strip()LOG_INFO("%s|%d|%s|%s", field_rule, field_num, struct_name, field_name)if (self._IsStructDefined(struct_name)) :self._is_layout = Falseelse :self._struct_name_list.append(struct_name)self._is_layout = Truecol_begin = self._colself._StructDefine(struct_name, field_num)col_end = self._colself._is_layout = Trueif repeated_num >= 1:field_rule = "repeated"elif field_rule == "required_struct":field_rule = "required"else:field_rule = "optional"self._LayoutOneField(field_rule, struct_name, field_name)actual_repeated_num = 1 if (repeated_num == 0) else repeated_numself._col += (actual_repeated_num-1) * (col_end-col_begin)else :self._col += 1returndef _IsStructDefined(self, struct_name) :for name in self._struct_name_list :if name == struct_name :return Truereturn Falsedef _StructDefine(self, struct_name, field_num) :"""嵌套结构定义"""self._col += 1self._LayoutStructHead(struct_name)self._IncreaseIndentation()self._field_index_list.append(1)while field_num > 0 :self._FieldDefine(0)field_num -= 1self._field_index_list.pop()self._DecreaseIndentation()self._LayoutStructTail()def _LayoutFileHeader(self) :"""生成PB文件的描述信息"""self._output.append("/**\n")self._output.append("* @file:   " + self._pb_file_name + "\n")self._output.append("* @author: jameyli <jameyli AT tencent DOT com>\n")self._output.append("* @brief:  这个文件是通过工具自动生成的,建议不要手动修改\n")self._output.append("*/\n")self._output.append("\n")def _LayoutStructHead(self, struct_name) :"""生成结构头"""if not self._is_layout :returnself._output.append("\n")self._output.append(" "*self._indentation + "message " + struct_name + "{\n")def _LayoutStructTail(self) :"""生成结构尾"""if not self._is_layout :returnself._output.append(" "*self._indentation + "}\n")self._output.append("\n")def _LayoutComment(self, comment) :# 改用C风格的注释,防止会有分行if not self._is_layout :returnif comment.count("\n") > 1 :if comment[-1] != '\n':comment = comment + "\n"comment = comment.replace("\n", "\n" + " " * (self._indentation + TAP_BLANK_NUM),comment.count("\n")-1 )self._output.append(" "*self._indentation + "/** " + comment + " "*self._indentation + "*/\n")else :self._output.append(" "*self._indentation + "/** " + comment + " */\n")def _LayoutOneField(self, field_rule, field_type, field_name) :"""输出一行定义"""if not self._is_layout :returnif field_name.find('=') > 0 :name_and_value = field_name.split('=')self._output.append(" "*self._indentation + field_rule + " " + field_type \+ " " + str(name_and_value[0]).strip() + " = " + self._GetAndAddFieldIndex()\+ " [default = " + str(name_and_value[1]).strip() + "]" + ";\n")returnif (field_rule != "required" and field_rule != "optional") :self._output.append(" "*self._indentation + field_rule + " " + field_type \+ " " + field_name + " = " + self._GetAndAddFieldIndex() + ";\n")returnif field_type == "int32" or field_type == "int64"\or field_type == "uint32" or field_type == "uint64"\or field_type == "sint32" or field_type == "sint64"\or field_type == "fixed32" or field_type == "fixed64"\or field_type == "sfixed32" or field_type == "sfixed64" \or field_type == "double" or field_type == "float" :self._output.append(" "*self._indentation + field_rule + " " + field_type \+ " " + field_name + " = " + self._GetAndAddFieldIndex()\+ " [default = 0]" + ";\n")elif field_type == "string" or field_type == "bytes" :self._output.append(" "*self._indentation + field_rule + " " + field_type \+ " " + field_name + " = " + self._GetAndAddFieldIndex()\+ " [default = \"\"]" + ";\n")else :self._output.append(" "*self._indentation + field_rule + " " + field_type \+ " " + field_name + " = " + self._GetAndAddFieldIndex() + ";\n")returndef _IncreaseIndentation(self) :"""增加缩进"""self._indentation += TAP_BLANK_NUMdef _DecreaseIndentation(self) :"""减少缩进"""self._indentation -= TAP_BLANK_NUMdef _GetAndAddFieldIndex(self) :"""获得字段的序号, 并将序号增加"""index = str(self._field_index_list[- 1])self._field_index_list[-1] += 1return indexdef _LayoutArray(self) :"""输出数组定义"""self._output.append("message " + self._sheet_name + "_ARRAY {\n")self._output.append("    repeated " + self._sheet_name + " items = 1;\n}\n")def _Write2File(self) :"""输出到文件"""pb_file = open(self._pb_file_name, "w+")pb_file.writelines(self._output)pb_file.close()class DataParser:"""解析excel的数据"""def __init__(self, xls_file_path, sheet_name,cs="S"):self._xls_file_path = xls_file_pathself._sheet_name = sheet_nameself._cs = cstry :self._workbook = xlrd.open_workbook(self._xls_file_path)except BaseException, e :print "open xls file(%s) failed!"%(self._xls_file_path)raisetry :self._sheet =self._workbook.sheet_by_name(self._sheet_name)except BaseException, e :print "open sheet(%s) failed!"%(self._sheet_name)raiseself._row_count = len(self._sheet.col_values(0))self._col_count = len(self._sheet.row_values(0))self._row = 0self._col = 0try:self._module_name = "tnt_deploy_" + self._sheet_name.lower() + "_pb2"sys.path.append(os.getcwd())exec('from '+self._module_name + ' import *');self._module = sys.modules[self._module_name]except BaseException, e :print "load module(%s) failed"%(self._module_name)raisedef Parse(self) :"""对外的接口:解析数据"""LOG_INFO("begin parse, row_count = %d, col_count = %d", self._row_count, self._col_count)item_array = getattr(self._module, self._sheet_name+'_ARRAY')()# 先找到定义ID的列id_col = 0for id_col in range(0, self._col_count) :info_id = str(self._sheet.cell_value(self._row, id_col)).strip()if info_id == "" :continueelse :breakfor self._row in range(4, self._row_count) :# 如果 id 是 空 直接跳过改行info_id = str(self._sheet.cell_value(self._row, id_col)).strip()if info_id == "" :LOG_WARN("%d is None", self._row)continueitem = item_array.items.add()self._ParseLine(item)LOG_INFO("parse result:\n%s", item_array)self._WriteReadableData2File(str(item_array))data = item_array.SerializeToString()self._WriteData2File(data)#comment this line for test .by kevin at 2013年1月12日 17:23:35LogHelp.close()def _ParseLine(self, item) :LOG_INFO("%d", self._row)self._col = 0while self._col < self._col_count :self._ParseField(0, 0, item)def _ParseField(self, max_repeated_num, repeated_num, item) :field_cs = str(self._sheet.cell_value(FIELD_CS_ROW, self._col))if field_cs.find(self._cs) < 0:self._col +=1returnfield_rule = str(self._sheet.cell_value(0, self._col)).strip()if field_rule == "required" or field_rule == "optional" :field_name = str(self._sheet.cell_value(2, self._col)).strip()if field_name.find('=') > 0 :name_and_value = field_name.split('=')field_name = str(name_and_value[0]).strip()field_type = str(self._sheet.cell_value(1, self._col)).strip()LOG_INFO("%d|%d", self._row, self._col)LOG_INFO("%s|%s|%s", field_rule, field_type, field_name)if max_repeated_num == 0 :field_value = self._GetFieldValue(field_type, self._row, self._col)# 有value才设值if field_value != None :item.__setattr__(field_name, field_value)self._col += 1else :if repeated_num == 0 :if field_rule == "required" :print "required but repeated_num = 0"raiseelse :for col in range(self._col, self._col + repeated_num):field_value = self._GetFieldValue(field_type, self._row, col)# 有value才设值if field_value != None :item.__getattribute__(field_name).append(field_value)self._col += max_repeated_numelif field_rule == "repeated" :# 2011-11-29 修改# 若repeated第二行是类型定义,则表示当前字段是repeated,并且数据在单列用分好相隔second_row = str(self._sheet.cell_value(FIELD_TYPE_ROW, self._col)).strip()LOG_DEBUG("repeated|%s", second_row);# exel有可能有小数点if second_row.isdigit() or second_row.find(".") != -1 :# 这里后面一般会是一个结构体max_repeated_num = int(float(second_row))read = self._sheet.cell_value(self._row, self._col)repeated_num = 0 if read == "" else int(self._sheet.cell_value(self._row, self._col))LOG_INFO("%s|%d|%d", field_rule, max_repeated_num, repeated_num)if max_repeated_num == 0 :print "max repeated num shouldn't be 0"raiseif repeated_num > max_repeated_num :repeated_num = max_repeated_numself._col += 1self._ParseField(max_repeated_num, repeated_num, item)else :# 一般是简单的单字段,数值用分号相隔# 一般也只能是数字类型field_type = second_rowfield_name = str(self._sheet.cell_value(FIELD_NAME_ROW, self._col)).strip()field_value_str = unicode(self._sheet.cell_value(self._row, self._col))#field_value_str = unicode(self._sheet.cell_value(self._row, self._col)).strip()# LOG_INFO("%d|%d|%s|%s|%s",#         self._row, self._col, field_rule, field_type, field_name, field_value_str)#2013-01-24 jamey#增加长度判断if len(field_value_str) > 0:if field_value_str.find(";\n") > 0 :field_value_list = field_value_str.split(";\n")else :field_value_list = field_value_str.split(";")for field_value in field_value_list :if field_type == "bytes":item.__getattribute__(field_name).append(field_value.encode("utf8"))else:item.__getattribute__(field_name).append(int(float(field_value)))self._col += 1elif field_rule == "required_struct" or field_rule == "optional_struct":field_num = int(self._sheet.cell_value(FIELD_TYPE_ROW, self._col))struct_name = str(self._sheet.cell_value(FIELD_NAME_ROW, self._col)).strip()field_name = str(self._sheet.cell_value(FIELD_COMMENT_ROW, self._col)).strip()LOG_INFO("%s|%d|%s|%s", field_rule, field_num, struct_name, field_name)col_begin = self._col# 至少循环一次if max_repeated_num == 0 :struct_item = item.__getattribute__(field_name)self._ParseStruct(field_num, struct_item)else :if repeated_num == 0 :if field_rule == "required_struct" :print "required but repeated_num = 0"raise# 先读取再删除掉struct_item = item.__getattribute__(field_name).add()self._ParseStruct(field_num, struct_item)item.__getattribute__(field_name).__delitem__(-1)else :for num in range(0, repeated_num):struct_item = item.__getattribute__(field_name).add()self._ParseStruct(field_num, struct_item)col_end = self._colmax_repeated_num = 1 if (max_repeated_num == 0) else max_repeated_numactual_repeated_num = 1 if (repeated_num==0) else repeated_numself._col += (max_repeated_num - actual_repeated_num) * ((col_end-col_begin)/actual_repeated_num)else :self._col += 1returndef _ParseStruct(self, field_num, struct_item) :"""嵌套结构数据读取"""# 跳过结构体定义self._col += 1while field_num > 0 :self._ParseField(0, 0, struct_item)field_num -= 1def _GetFieldValue(self, field_type, row, col) :"""将pb类型转换为python类型"""field_value = self._sheet.cell_value(row, col)LOG_INFO("%d|%d|%s", row, col, field_value)try:if field_type == "int32" or field_type == "int64"\or  field_type == "uint32" or field_type == "uint64"\or field_type == "sint32" or field_type == "sint64"\or field_type == "fixed32" or field_type == "fixed64"\or field_type == "sfixed32" or field_type == "sfixed64" :if len(str(field_value).strip()) <=0 :return Noneelse :return int(field_value)elif field_type == "double" or field_type == "float" :if len(str(field_value).strip()) <=0 :return Noneelse :return float(field_value)elif field_type == "string" :field_value = unicode(field_value)if len(field_value) <= 0 :return Noneelse :return field_valueelif field_type == "bytes" :field_value = unicode(field_value).encode('utf-8')if len(field_value) <= 0 :return Noneelse :return field_valueelse :return Noneexcept BaseException, e :print "parse cell(%u, %u) error, please check it, maybe type is wrong."%(row, col)raisedef _WriteData2File(self, data) :file_name = "tnt_deploy_" + self._sheet_name.lower() + ".data"file = open(file_name, 'wb+')file.write(data)file.close()def _WriteReadableData2File(self, data) :file_name = "tnt_deploy_" + self._sheet_name.lower() + ".txt"file = open(file_name, 'wb+')file.write(data)file.close()if __name__ == '__main__' :"""入口"""if len(sys.argv) < 3 :print "Usage: %s sheet_name(should be upper) xls_file" %(sys.argv[0])sys.exit(-1)# option 0 生成proto和data 1 只生成proto 2 只生成data,op = 0if len(sys.argv) > 3 :op = int(sys.argv[3])sheet_name =  sys.argv[1]if (not sheet_name.isupper()):print "sheet_name should be upper"sys.exit(-2)xls_file_path =  sys.argv[2]CS = "CS"if len(sys.argv) > 4:CS = sys.argv[4] #可指定需要导出的列C,S,CSif op == 0 or op == 1:try :tool = SheetInterpreter(xls_file_path, sheet_name,CS)tool.Interpreter()except BaseException, e :print "Interpreter Failed!!!"print esys.exit(-3)print "Interpreter Success!!!"if op == 0 or op == 2:try :parser = DataParser(xls_file_path, sheet_name,CS)parser.Parse()except BaseException, e :print "Parse Failed!!!"print esys.exit(-4)print "Parse Success!!!"

转载于:https://my.oschina.net/u/2504104/blog/3016442

一个好用的导出excel数据为protobuf的工具相关推荐

  1. php把数据创建一个表格,PHP创建(导出Excel数据表格)

    /** * 创建(导出Excel数据表格) * @param  array   $list 要导出的数组格式的数据 * @param  string  $filename 导出的Excel表格数据表的 ...

  2. Vue导出Excel数据表格

    这两天在做一个有关Vue框架导出Excel数据表格的项目练习,因为之前并未写过有关导出功能的练习,所以有感而发记录一下,也请各位一起共同各抒己见.(这是我第一次写博客,不足之处敬请指教) 我的情况是后 ...

  3. python导入excel数据-Python数据处理之导入导出excel数据

    欢迎点击上方"AntDream"关注我 .Python的一大应用就是数据分析了,而数据分析中,经常碰到需要处理Excel数据的情况.这里做一个Python处理Excel数据的总结, ...

  4. php导出excel数据使用csv替代xls格式

    为什么80%的码农都做不了架构师?>>>    php导出excel数据使用csv替代xls格式 一直以来需要将某些后台数据导出来以供运营人员查看,因为他们都用excel.所以最初的 ...

  5. java excel data 导入数据_java实现导入导出excel数据

    项目需要,要实现一个导入导出excel的功能,于是,任务驱动着我学习到了POI和JXL这2个java操作Excel的插件. 一.POI和JXL介绍 1.POI:是对所有office资源进行读写的一套工 ...

  6. 【译】Asp.Net 导出 Excel 数据的9种方案

    简介 Excel 的强大之处在于它不仅仅只能打开Excel格式的文档,它还能打开CSV格式.Tab格式.website table 等多钟格式的文档.它具备自动识别行号,字符,格式化数字等功能,例如: ...

  7. 自定义注解导出excel数据

    自定义注解导出excel数据 利用自定义注解方式,对数据列表进行简单的导出操作.即在实体对象的属性域上添加导出标识的注解,在对实体进行导出时,利用自定义注解进行反射的方法,获取实体需要导出的属性及值. ...

  8. toad导入数据_Oracle 使用TOAD实现导入导出Excel数据

    在Oracle应用程序的开发过程中,访问数据库对象和编写SQL程序是一件乏味且耗费时间的工作,对数据库进行日常管理也是需要很多SQL脚本才能完成的.Quest Software为此提供了高效的Orac ...

  9. java 动态导入excel_java实现导入导出excel数据

    项目需要,要实现一个导入导出excel的功能,于是,任务驱动着我学习到了POI和JXL这2个java操作Excel的插件. 一.POI和JXL介绍 1.POI:是对所有office资源进行读写的一套工 ...

最新文章

  1. C语言条件编译及编译预处理阶段
  2. HoughLinesP函数(概率检测直线)
  3. 直播 | DSTC 8“基于Schema的对话状态追踪”竞赛冠军方案解读
  4. CAN总线技术在船舶监控系统的应用
  5. IE6,7下实现white-space:pre-wrap;
  6. stvd能编译c语言,stvd+stm8s单片机程序编译报错
  7. mysql查询excel表_使用SQL语句实现对Excel工作表数据进行查询的方法
  8. windows服务启动程序_在Windows上快速启动程序的5种方法
  9. 关于bootstrapValidator 表单校验remote出现两次重复提交才能验证通过问题处理
  10. removeNode is not defined removeNode is not a function
  11. 总价合同、成本补偿合同、工料合同
  12. 配置H3C设备无线AP多vlan步骤
  13. JSON格式的文件转换对象存入数据库
  14. 达芬奇密码 第五十九章
  15. sm2262en怎么量产?sm2262en量产工具,sm2263en开卡软件,sm2263en、sm2262en使用量产工具成功开卡的方法指引
  16. win10计算机窗口览,Win10窗口预览管理工具
  17. 使用wangEditor富文本编辑器遇到的问题总结
  18. 我对移动支付的看法_研究用户对移动支付的看法论文
  19. 在Chrome中打印CSDN博客内容
  20. python运势预测程序_基于Python的星座运势接口调用代码实例

热门文章

  1. js 怎么知道打印完成_你真的知道缩放打印怎么用吗?
  2. 2012高等学校计算机等级考试试卷二级 vb.net程序设计,2012上海市高等校计算机等级考试试卷二级VBNET程序设计.docx...
  3. linux查看电脑硬件信息,Linux下查看电脑硬件配置【转】
  4. 计算机应用技术高数挂科,这7个专业难度太大,挂科率很高,只有学神才敢报考...
  5. android bundle传递参数,android – 使用bundle将数据从一个活动传递...
  6. linux睡眠进程,linux一个进程如何睡眠
  7. java分库校验商户流水号是否重复,asp中用数据库生成不重复的流水号
  8. 计算机硬件配置和软件有哪些,BIM软件对电脑硬件配置有什么要求?
  9. js <->java 时区处理
  10. vue 指令 v-model