精华内容
下载资源
问答
  • 最近项目需求需要制作一个表格展示效果,先看下...不用纠结 RecyclerView 完完全全可以实现这种效果,无外乎可能就是稍微复杂些RecyclerView 实现思路:最外层采用 HorizontalScrollView,保证表格可以左右进行滑动...

    最近项目需求需要制作一个表格展示效果,先看下UI图吧:

    11cf8f5ab396?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

    image.png

    刚开始接收到这个需求的时候,第一反应就是使用 RecyclerView 来进行实现,谁让 RecyclerView 那么牛逼呢?不用纠结 RecyclerView 完完全全可以实现这种效果,无外乎可能就是稍微复杂些

    RecyclerView 实现思路:

    最外层采用 HorizontalScrollView,保证表格可以左右进行滑动

    内层使用 RecyclerView,而使用 RecyclerView 时需要使用到 getItemViewType 这个方法来规定条目的类型(第一行title以及合计可以认为是同一种类型,而“沈阳”那一个稍微大一点的条目可以认为是第二种类型

    类型一:这个类型布局就非常简单了,采用 LInearLayout 就可以非常简单的实现

    类型二:可以采用水平的 LinearLayout 包裹 TextView 以及 RecyclerView 来进行实现

    上面仅仅是介绍了我最开始采用的方案,当然缺点非常多:

    使用上面方案时,需要考虑列的宽度问题,要么宽度直接在布局中写死(每列中文字长度不一样,可能会出现第一行与第二行的列错位情况),要么根据服务器返回的数据动态获取每列中最长字符串所需要占用的宽度进行动态设置

    表格一般都会存在排序功能(当然我这个项目中暂时还未出现),如果出现需要对列进行升序或降序排序,那就呵呵了,自己想办法去吧,想想都痛苦

    说了这么多并不是贬低 RecyclerView 的意思,因为 RecyclerView 本身的定义就不是专门用来做这种复杂表格的(有说错的地方,欢迎在评论中留言),你让 RecyclerView 去实现这种效果就有点.......

    下面来介绍一下今天的主角:SmartTable —— 好用漂亮的 Android 表格框架

    先说一下 SmartTable 都支持的功能吧,具体例子后面再给出:

    快速配置自动生成表格;

    自动计算表格宽高

    表格列标题组合

    表格固定左序列、顶部序列、第一行、列标题、统计行

    自动统计,排序(自定义统计规则)

    表格图文、序列号、列标题格式化

    表格各组成背景、文字、网格、padding 等配置

    表格批注

    表格内容、列标题点击事件

    缩放模式和滚动模式

    注解模式

    内容多行显示

    分页模式

    首尾动态添加数据

    丰富的格式化

    支持二维数组展示(用于类似日程表,电影选票等)

    导入 excel(支持颜色,字体,背景,批注,对齐,图片等基本 Excel 属性)

    表格合并单元(支持注解合并,支持自动合并)

    支持其他刷新框架 SmartRefreshLayout

    可配置表格最小宽度(小于该宽度自动适配)

    支持直接 List 或数组字段转列

    支持 Json 数据直接转换成表格

    支持表格网格指定行列显示

    看介绍是不是感觉叼的不要不要的,不过呢,我也是刚使用这个框架,在这里也仅仅是介绍一些开发中常用的,其他的自己去尝试吧

    如何使用

    引用:添加 JitPack repository 到你的 build 文件

    allprojects {

    repositories {

    ...

    maven { url 'https://www.jitpack.io' }

    }

    }

    增加依赖

    dependencies {

    compile 'com.github.huangyanbin:SmartTable:2.0'

    }

    使用方式

    SmartTable 的使用方式有两种:

    采用注解的形式

    基本模式,手动配置行与列

    一、注解方式

    步骤一:在布局文件中使用 SmartTable

    android:id="@+id/table"

    android:layout_width="match_parent"

    android:layout_height="match_parent" />

    步骤二:定义表格(自定义bean对象)

    @SmartTable(name = "销售计划表")

    public class UserInfo {

    public UserInfo(String city, int name, int count, int restaurant, int ka, int wholesale, int industry, int other) {

    this.city = city;

    this.name = name;

    this.count = count;

    this.restaurant = restaurant;

    this.ka = ka;

    this.wholesale = wholesale;

    this.industry = industry;

    this.other = other;

    }

    // name:版块名称,count:目标值,restaurant:餐饮数量,ka:KA数量,wholesale:流通批发数量,industry:工业加工数量,other:其它数量

    @SmartColumn(id = 0, name = "部门/渠道", autoMerge = true)

    private String city;

    @SmartColumn(id = 1, name = "板块")

    private int name;

    @SmartColumn(id = 2, name = "目标值")

    private int count;

    @SmartColumn(id = 3, name = "餐饮")

    private int restaurant;

    @SmartColumn(id = 4, name = "KA")

    private int ka;

    @SmartColumn(id = 5, name = "流通批发")

    private int wholesale;

    @SmartColumn(id = 6, name = "工业加工")

    private int industry;

    @SmartColumn(id = 7, name = "其他")

    private int other;

    }

    步骤三:绑定数据(完成)

    public class MainActivity extends AppCompatActivity {

    private SmartTable table;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    List list = new ArrayList<>();

    table = findViewById(R.id.table);

    list.add(new UserInfo("沈阳",100, 150, 50, 240, 1100, 450, 23458));

    list.add(new UserInfo("沈阳",100, 150, 50, 240, 1100, 450, 23458));

    list.add(new UserInfo("沈阳",100, 150, 50, 240, 1100, 450, 23458));

    list.add(new UserInfo("沈阳",100, 150, 50, 240, 1100, 450, 23458));

    list.add(new UserInfo("乌鲁木齐",100, 150, 50, 240, 1100, 450, 23458));

    list.add(new UserInfo("乌鲁木齐",100, 150, 50, 240, 1100, 450, 23458));

    list.add(new UserInfo("乌鲁木齐",100, 150, 50, 240, 1100, 450, 23458));

    list.add(new UserInfo("乌鲁木齐",100, 150, 50, 240, 1100, 450, 23458));

    list.add(new UserInfo("沈阳",100, 150, 50, 240, 1100, 450, 23458));

    list.add(new UserInfo("沈阳",100, 150, 50, 240, 1100, 450, 23458));

    list.add(new UserInfo("沈阳",100, 150, 50, 240, 1100, 450, 23458));

    list.add(new UserInfo("沈阳",100, 150, 50, 240, 1100, 450, 23458));

    table.setData(list);

    table.getConfig().setContentStyle(new FontStyle(50, Color.BLUE));

    }

    }

    是不是分分钟实现,效果图如下:

    11cf8f5ab396?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

    image.png

    二、基本方式,手动创建行与列

    步骤一:在布局文件中使用 SmartTable

    android:id="@+id/table"

    android:layout_width="match_parent"

    android:layout_height="match_parent" />

    步骤二:定义表格(自定义bean对象),与采用注解方式唯一的不同就是不在使用 @SmartColumn 与 @SmartColumn 进行标注

    public class User {

    public User(String city, int name, int count, int restaurant, int ka, int wholesale, int industry, int other) {

    this.city = city;

    this.name = name;

    this.count = count;

    this.restaurant = restaurant;

    this.ka = ka;

    this.wholesale = wholesale;

    this.industry = industry;

    this.other = other;

    }

    // name:版块名称,count:目标值,restaurant:餐饮数量,ka:KA数量,wholesale:流通批发数量,industry:工业加工数量,other:其它数量

    private String city;

    private int name;

    private int count;

    private int restaurant;

    private int ka;

    private int wholesale;

    private int industry;

    private int other;

    }

    步骤三:手动创建列字段

    //普通列

    Column city = new Column<>("部门/渠道", "city");

    Column name = new Column<>("板块", "name");

    Column count = new Column<>("目标值", "count");

    Column restaurant = new Column<>("餐饮", "restaurant");

    Column ka = new Column<>("KA", "ka");

    Column wholesale = new Column<>("流通批发", "wholesale");

    Column industry = new Column<>("工业加工", "industry");

    Column other = new Column<>("其他", "other");

    //设置该列当字段相同时自动合并

    city.setAutoMerge(true);

    步骤四:设置单元格内容

    //设置单元格内容

    List list = new ArrayList<>();

    list.add(new User("沈阳", 100, 150, 50, 240, 1100, 450, 23458));

    list.add(new User("沈阳", 100, 150, 50, 240, 1100, 450, 23458));

    list.add(new User("沈阳", 100, 150, 50, 240, 1100, 450, 23458));

    list.add(new User("沈阳", 100, 150, 50, 240, 1100, 450, 23458));

    list.add(new User("乌鲁木齐", 100, 150, 50, 240, 1100, 450, 23458));

    list.add(new User("乌鲁木齐", 100, 150, 50, 240, 1100, 450, 23458));

    list.add(new User("乌鲁木齐", 100, 150, 50, 240, 1100, 450, 23458));

    list.add(new User("乌鲁木齐", 100, 150, 50, 240, 1100, 450, 23458));

    list.add(new User("沈阳", 100, 150, 50, 240, 1100, 450, 23458));

    list.add(new User("沈阳", 100, 150, 50, 240, 1100, 450, 23458));

    list.add(new User("沈阳", 100, 150, 50, 240, 1100, 450, 23458));

    list.add(new User("沈阳", 100, 150, 50, 240, 1100, 450, 23458));

    步骤五:把数据绑定到 SmartTable 上

    //表格数据 datas 是需要填充的数据

    TableData tableData = new TableData<>("表格名", list, city, name, count, restaurant, ka, wholesale, industry, other);

    //设置数据

    table = findViewById(R.id.table);

    table.setTableData(tableData);

    table.getConfig().setContentStyle(new FontStyle(50, Color.BLUE));

    是不是也是分分钟的事,效果图是一样的就不贴了

    优劣势:(个人看法,欢迎吐槽)

    注解方式

    使用上简单,几行代码就可以创建一个表格

    不能实现列的动态创建

    不能实现列的排序

    基本方式:

    使用上稍稍比注解方式麻烦一点

    可以实现列的动态创建(根据服务器返回的列的数量动态创建表格)

    可以实现点击列,对列进行升序以及倒序排列

    注解的其他功能

    @SmartTable:表格注解,用于生成表格

    可用属性:

    name:表格名

    count:是否显示统计行

    pageSize:页数量

    currentPage:当前页

    目测没什么用,可能还没找到技巧,先记录下........

    @SmartColumn列,用于注解列

    name:列标题

    id:列排列位置(id越小,位置越靠前)

    parent:父列名称(不设置则没有父列)

    align:列对其方式,默认居中

    type:设置是否查询下一级,有 ColumnType.Own,ColumnType.Child,两个值可以设置,假设 UserInfo 有个属性是 Family family 对象,你想解析 faily 对象的属性 monther,father 两个属性,则需要设置 Child,并在 monther,father 下添加相对应的注解@SmartColumn,否则只解析到 Family,默认是 Own。

    autoMerge:设置是否自动合并,假设你返回的数据格式化之后 该列附近数据有相同,则会自动合并成一个单元格,默认不开启合并。

    maxMergeCount:合并最大数量

    autoCount:是否开启统计,table 开启显示统计行,设置 autoCount 为 true,则该列可以自动统计,默认为 false。

    fixed:是否固定该列, fixed 设置为 true,该列滚动到最左边时,可以自动固定住。

    基本方法介绍

    Column 类的常用方法

    setAutoCount(boolean isAutoCount):设置自动排序(默认升序)

    isReverseSort:是否是反序排列

    setComparator:设置排序比较

    setCountFormat:统计格式化

    OnColumnItemClickListener:列内容点击事件

    setFixed:滑动到表格左边时固定列

    setTextAlign:设置开启自动合并

    setMaxMergeCount:设置开启最大数量

    setDrawFormat:设置绘制样式格式化

    setFormat:设置文字格式化

    TableData 类常用方法

    setSortColumn:设置排序列

    settitleDrawFormat:设置列标题格式化

    setXSequenceFormat:设置顶部序列号格式化

    setYSequenceFormat:设置左边序列号格式化

    setShowCount:设置是否显示统计

    setTitleDrawFormat:设置列标题绘制格式化

    setXSequenceFormat :设置 X 序号行文字格式化

    setYSequenceFormat :设置 Y 序号行文字格式化

    setUserCellRange(List userCellRange) :设置添加自定义合并规则

    TableConfig 类常用方法

    setContentStyle :设置内容文字样式

    setYSequenceStyle :设置左边序列文字样式

    setXSequenceStyle :设置顶部序列文字样式

    setColumnTitleStyle :设置列标题文字样式

    setTableTitleStyle :设置表格标题文字样式

    setCountStyle :设置统计行样式

    setColumnTitleGridStyle :设置列标题网格样式

    setGridStyle :设置内容网格样式

    setVerticalPadding :设置网格列 padding

    setHorizontalPadding :设置网格行 padding

    setYSequenceBackgroundColor :设置左序列背景

    setXSequenceBackgroundColor :设置横序行背景

    setColumnTitleBackgroundColor :设置列标题背景

    setContentBackgroundColor :设置内容背景

    setCountBackgroundColor :设置统计行背景

    setFixedYSequence :固定左侧

    setFixedXSequence :固定顶部

    setFixedTitle :固定列标题

    setFixedCountRow :固定统计行

    setColumnTitleVerticalPadding :列标题上下 padding

    setColumnTitleHorizontalPadding :增加列标题左右 padding

    setSequenceGridStyle :序列网格样式

    columnTitleGridStyle :列标题网格样式

    setShowXSequence :设置是否显示顶部序号列

    setShowYSequence :设置是否显示左侧序号列

    setShowTableTitle :设置是否显示表格标题

    isShowColumnTitle :设置是否显示列标题

    setMinTableWidth :设置表格最小宽度

    SmartTable 类的常用方法

    setOnColumnClickListener :设置列标题点击事件

    setSortColumn :设置排序列

    setZoom(boolean zoom,float maxZoom,float minZoom) :设置是否开启缩放

    addData(List t, boolean isFoot) :添加新数据

    setSelectFormat :设置选中 Cell 样式

    notifyDataChanged :重新计算布局

    相关文章推荐:

    展开全文
  • java使用freemarker导出复杂的excel表格

    千次阅读 2020-04-07 08:14:55
    正常导出excel表格使用的poi,但是导出复杂的excel有点困难,但是可以使用freemaker模板来导出复杂的excel。 都是先生成一个Excel表格的模板,最好是增加一行数据。具体看图里面的步骤。 项目整体结构 下面就直接...

    正常导出excel表格使用的poi,但是导出复杂的excel有点困难,但是可以使用freemaker模板来导出复杂的excel。

    • 都是先生成一个Excel表格的模板,最好是增加一行数据。具体看图里面的步骤。
      在这里插入图片描述
    • 项目整体结构
      在这里插入图片描述
    • 下面就直接看代码
    public class Data {
    //代码复制之后直接就可以运行了
        public static void main(String[] args) {
            demo();
        }
    
        public static void demo() {
            // 项目下的template路径
            String path = new File("").getAbsolutePath() + "\\template";
            Map<String, Object> map = new HashMap<String, Object>();
            // 模板所在的路径
            map.put("tempFoldPath", path);
            // 生成的路径
            map.put("file", path + "/采购订单.xls");
            // 模板名称
            map.put("tampPath", "采购订单.ftl");
            // 最后生成的表格的名称
            map.put("excelName", "采购订单-" + "Demo" + ".xls");
            // 封装数据
            Map<String, Object> exlParam = new HashMap<>();
            exlParam.put("findList", new Data().list());
            // 调用方法,返回浏览器访问的地址
            String downloadUrl = ExportExcelUtil.exportExcel(map, exlParam);
        }
    
        // 自己造假数据,正常来说都是从数据库查询出来拼装数据的
        public List<Purbill> list() {
            List<Purbill> purbillList = new ArrayList<>();
            purbillList.add(new Purbill("1", "2", "名称", "采购名称", "规格参数", "参数指标", "场地", "10吨", 10, 20.2, 220.2, "品牌"));
            return purbillList;
        }
    
    }
    
    class Purbill {
        private String bidId;
        private String billno;
        private String categoryName;
        private String purname;
        private String specparams;
        private String paramnorm;
        private String productAddress;
        private String unit;
        private Integer nums;
        private Double price;
        private Double totalprice;
        private String brand;
    
        public Purbill(String bidId, String billno, String categoryName, String purname, String specparams,
                String paramnorm, String productAddress, String unit, Integer nums, Double price, Double totalprice,
                String brand) {
            super();
            this.bidId = bidId;
            this.billno = billno;
            this.categoryName = categoryName;
            this.purname = purname;
            this.specparams = specparams;
            this.paramnorm = paramnorm;
            this.productAddress = productAddress;
            this.unit = unit;
            this.nums = nums;
            this.price = price;
            this.totalprice = totalprice;
            this.brand = brand;
        }
    
        public String getBidId() {
            return bidId;
        }
    
        public void setBidId(String bidId) {
            this.bidId = bidId;
        }
    
        public String getBillno() {
            return billno;
        }
    
        public void setBillno(String billno) {
            this.billno = billno;
        }
    
        public String getCategoryName() {
            return categoryName;
        }
    
        public void setCategoryName(String categoryName) {
            this.categoryName = categoryName;
        }
    
        public String getPurname() {
            return purname;
        }
    
        public void setPurname(String purname) {
            this.purname = purname;
        }
    
        public String getSpecparams() {
            return specparams;
        }
    
        public void setSpecparams(String specparams) {
            this.specparams = specparams;
        }
    
        public String getParamnorm() {
            return paramnorm;
        }
    
        public void setParamnorm(String paramnorm) {
            this.paramnorm = paramnorm;
        }
    
        public String getProductAddress() {
            return productAddress;
        }
    
        public void setProductAddress(String productAddress) {
            this.productAddress = productAddress;
        }
    
        public String getUnit() {
            return unit;
        }
    
        public void setUnit(String unit) {
            this.unit = unit;
        }
    
        public Integer getNums() {
            return nums;
        }
    
        public void setNums(Integer nums) {
            this.nums = nums;
        }
    
        public Double getPrice() {
            return price;
        }
    
        public void setPrice(Double price) {
            this.price = price;
        }
    
        public Double getTotalprice() {
            return totalprice;
        }
    
        public void setTotalprice(Double totalprice) {
            this.totalprice = totalprice;
        }
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
    }
    

    主要是两个map,一个map是封装模板的位置和生成表格的位置,第二个map是封装的数据。正常来说导出表格之后都是返回url请求的地址,这样在真实项目中根据地址就可以下载出来了。

    • 下面是一个excel导出的一个工具类
    public class ExportExcelUtil {
    
        public static String exportExcel(Map<String, Object> map, Map<String, Object> exlParam) {
            Template dateTmp = null;
            Writer fw = null;
            InputStream in = null;
            OutputStream out = null;
            try {
                // 此处需要给你个版本信息,Configuration cfg = new Configuration();这个方法已经过时了
                Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);
                String tempFoldPath = (String) map.get("tempFoldPath"); // 模板所在的路径
                String file = (String) map.get("file");// 生成表格模板的路径
                String tampPath = (String) map.get("tampPath");// 模板名称
                String excelName = (String) map.get("excelName");// 最后生成表格的名称
    
                // **********初始化参数**********
                File tempFoldFile = new File(tempFoldPath);
                if (!tempFoldFile.exists()) {
                    tempFoldFile.mkdirs();
                }
                cfg.setDirectoryForTemplateLoading(tempFoldFile);
                cfg.setDefaultEncoding("UTF-8");
                cfg.setTemplateUpdateDelay(0);
                cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
                // **********获取freemaker模板**********
                dateTmp = cfg.getTemplate(tampPath);
    
                // **********将数据写入freemaker模板**********
                fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(file)), "UTF-8"));
                dateTmp.process(exlParam, fw);
    
                // **********从freemaker模板读出数据写到Excel表格并生成出来**********
                String fileDir = "excel";
                // 文件保存目录  项目目录下面
                String filePath =  new File("").getAbsolutePath();
                // 生成保存文件路径
                String createPath = filePath + "/" + fileDir + "/";
                // 构建源文件
                File files = new File(file);
                // 文件夹不存在就创建
                createFolder(createPath);
                // 删除原来的文件
                deleteFile(createPath + excelName);
                // 构建目标文件
                File fileCopy = new File(createPath + excelName);
                // 目标文件不存在就创建
                if (!(fileCopy.exists())) {
                    fileCopy.createNewFile();
                }
                // 源文件创建输入流
                in = new FileInputStream(files);
                // 目标文件创建输出流
                out = new FileOutputStream(fileCopy, true);
                // 创建字节数组
                byte[] temp = new byte[1024];
                int length = 0;
                // 源文件读取一部分内容
                while ((length = in.read(temp)) != -1) {
                    // 目标文件写入一部分内容
                    out.write(temp, 0, length);
                }
                // 资源服务器访问目录 这边需要配置tomcat的虚拟路径,就可以直接在url上面下载表格了
                String serverPath = "resourceServer";
                String savePath = "/" + serverPath + "/" + fileDir + "/" + excelName;
                // 服务器图片访问目录
                return savePath;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            } finally {
                try {
                    fw.close();
                    // 关闭文件输入输出流
                    in.close();
                    out.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
    
            }
    
        }
    
        // 创建文件
        public static boolean createFolder(String path) {
            File file = new File(path);
            if (!file.exists()) {
                return file.mkdir();
            } else {
                return true;
            }
        }
    
        public static boolean deleteFile(String filePath) {// 删除单个文件
            boolean flag = false;
            File file = new File(filePath);
            if (file.exists() && file.isFile()) {
                file.delete();// 文件删除
                flag = true;
            }
            return true;
        }
    
    }
    

    这个也不用多说,里面注释基本上已经解释清楚了,

    • 因为数据放到freemaker模板里面了所以只需要使用freemaker模板的语法取出数据存放在模板里面就可以了
      在这里插入图片描述
    • Excel导出打开出现问题的原因
      当office2010之前的版本打开会出现格式不正确的提示,然后点击确定之后还是报格式错误或者可以打开但是没有数据,这种解决方法只需要将ss:ExpandedRowCount这个值设置和行数相等或者设置大一点就不会出现这种问题了。
      在这里插入图片描述
      错误提示
      在这里插入图片描述
      Demo地址:https://files.cnblogs.com/files/yangk1996/FreeMaker.zip
    展开全文
  • 主要介绍 word 文档中插入图片、设置图片大小;插入表格、设置表格样式、字体样式;章节设置:页面大小、边距等;设置页眉页脚等方法。

    Python-docx 模块读写 Word 文档基础(二):图片、表格,表格样式,章节设置,页眉页脚等

    前言:

    上一篇博客介绍了 python-docx 模块如何 创建 word 文档、设置段落格式、字体格式等 ,本篇博客将对在日常使用 word 文档的其他操作进行介绍。

    主要内容有:

    1、插入图片、设置图片大小;
    2、插入表格、设置表格样式、字体样式;
    3、章节设置:页面大小、边距等;
    4、设置页眉页脚。

    1、插入图片、设置大小:

    上篇博客简单的介绍了插入图片的方法,但是没介绍图片大小的设置方法:

    # 导入模块
    from docx import Document
    # 此模块中包含 docx 中各类单位方法
    from docx import shared
    
    doc = Document()
    doc.add_heading('python-docx 基础讲解(二)')
    
    # 在文档中增加图片,并对设置图片大小
    # 当只设置一个方向的长度(宽或高)时,另一方向会自动缩放
    doc.add_picture('1.png',width=shared.Inches(1))  # 按英寸设置
    doc.add_picture('1.png',height=shared.Cm(2))  # 按厘米设置
    
    # 保存文件
    doc.save('test2.docx')
    

    注:当只设置图片一个方向的尺寸(宽或高)时,另一方向会自动缩放。

    以上设置后文档截图:

    在这里插入图片描述

    2、插入表格、设置格式:

    1、在文档中增加表格,并添加文字:

    # 在文档中增加表格,并添加文字
    table1 = doc.add_table(2,3) # 添加一个2行3列的表格,表格样式为None
    "add_table(self, rows, cols, style=None):"
    table1.cell(0,0).text = '0'  # 给表格单元格赋值
    
    # 获取表格对象所有单元格对象列表
    print(table1._cells)
    # ------运行结果------
    # [<docx.table._Cell object at 0x000002131AF996C8>,
    # <docx.table._Cell object at 0x000002131AF99608>,
    # <docx.table._Cell object at 0x000002131AF99648>,
    # <docx.table._Cell object at 0x000002131AF99688>,
    # <docx.table._Cell object at 0x000002131AF99588>,
    # <docx.table._Cell object at 0x000002131AF995C8>]
    # ------运行结果------
    
    # 对单元格对象设置文字
    for i,cell in enumerate(table1._cells):
        cell.text = str(i)
    

    注:在word文档中增加表格时,会返回一个 table 对象。table对象中包含单元格 cell 对象,单元格写入数据就是设置 cell 对象的 text 值。

    插入的表格截图:

    在这里插入图片描述

    2、设置表格样式:

    从增加表格方法:add_table(self, rows, cols, style=None),可以看出在创建表格时,就可以对表格样式进行设置。

    可通过下面的方法获取 word 文档中 默认的表格样式:

    # 获取所有表格样式
    from docx.enum.style import WD_STYLE_TYPE
    
    styles = doc.styles
    for style in styles:
        if style.type == WD_STYLE_TYPE.TABLE:
            print(style)
    '''
    可设置的表格样式:
    _TableStyle('Normal Table') id: 187730312
    _TableStyle('Table Grid') id: 187730312
    _TableStyle('Light Shading') id: 187730376
    _TableStyle('Light Shading Accent 1') id: 187730312
    _TableStyle('Light Shading Accent 2') id: 187730376
    _TableStyle('Light Shading Accent 3') id: 187730312
    _TableStyle('Light Shading Accent 4') id: 187730376
    _TableStyle('Light Shading Accent 5') id: 187730312
    _TableStyle('Light Shading Accent 6') id: 187730376
    _TableStyle('Light List') id: 187730312
    ...
    内容很多,可以自己尝试运行打印一下
    '''
    

    以上获取的表格样式,对应word文档里的这些表格样式:

    在这里插入图片描述
    英文也不复杂,大家可以对照一下。

    设置表格样式:

    表格在创建时可及可指定格式:

    doc.add_table(2,3,style ='Table Grid' )
    

    也可在创建后进行设置:

    # 为表格设置统一样式:
    table1.style = 'Table Grid'
    

    设置表格样式后表格截图:

    在这里插入图片描述
    这样就比较接近日常使用的表格了。

    3、其他表格常用方法:

    # 表格设置自动调整列宽,(默认也为真)
    table1.autofit = True
    
    # 为表格对象增加列
    table1.add_column(shared.Inches(3)) # 需指定宽度
    "add_column(self, width):"
    
    # 为表格对象增加行
    table1.add_row() # 只能逐行添加
    "add_row(self):"
    

    获取表格对象的一些属性:

    # 获取行对象
    row0 = table1.rows[0]
    print(row0)
    # 获取列对象
    col0 = table1.columns[0]
    
    # 获取表格一行的单元格对象列表
    row0_cells = table1.row_cells(0)
    print(row0_cells)
    # 运行结果
    # [<docx.table._Cell object at 0x000000000B311C88>,
    # <docx.table._Cell object at 0x000000000B311AC8>,
    # <docx.table._Cell object at 0x000000000B311B08>,
    # <docx.table._Cell object at 0x000000000B311A48>]
    
    # 获取一列的单元格对象列表
    col_0_cells = table1.column_cells(0)
    print(col_0_cells)
    # 运行结果
    # [<docx.table._Cell object at 0x000000000B312F88>,
    # <docx.table._Cell object at 0x000000000B312CC8>,
    # <docx.table._Cell object at 0x000000000B31A108>]
    

    4、设置表格内单元格对齐方式,合并单元格:

    # 设置单元格对齐方式
    # 垂直对齐方式
    from docx.enum.table import WD_ALIGN_VERTICAL
    table1.cell(0,0).vertical_alignment = WD_ALIGN_VERTICAL.TOP
    
    # 合并单元格
    cell_new = table1.cell(2,0).merge(table1.cell(2,1))
    # 返回一个新单元格对象
    print(cell_new)
    # <docx.table._Cell object at 0x000000000B312F08>
    # 要继续合并的话,可用此单元格再次使用 merge 方法
    

    对表格增加行、列,合并单元格后表格截图:

    在这里插入图片描述

    5、设置单元格字体格式:

    单元格内其实也是有 paragraph 对象的,即对单元格内字体设置方式,和对段落中文字格式设置方法一样。

    cell_par = cell_new.paragraphs[0] # 获取到对象
    # 设置对齐方式
    from docx.enum.text import WD_ALIGN_PARAGRAPH
    cell_par.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
    # 获取 run 对象
    cell_run = cell_new.paragraphs[0].runs[0]
    # 设置字体
    cell_run.font.name = 'Times New Roman'
    from docx.oxml.ns import qn
    cell_run.font.element.rPr.rFonts.set(qn('w:eastAsia'),'楷体')
    # 设置字体颜色
    from docx.shared import RGBColor
    cell_run.font.color.rgb = RGBColor(255,55,55) # 红色
    

    表格截图:

    在这里插入图片描述

    3、设置章节、页面设置等:

    章节 也是 word 文档中一个块级元素,相较于段落块级元素它的范围应该更大一点。一般来说:一个 word 文档包含多个章节、一个章节包含多个 run 块级元素。

    一个word文档被建立时至少包含一个章节:

    # word文档中章节 section 对象
    sec = doc.sections
    print(sec) # <docx.section.Sections object at 0x000000000B312E88>
    print(len(sec)) # 1
    

    1、新建章节:

    # 新建一个章节
    doc.add_section()
    print(len(sec)) # 2
    

    2、获取文档页面边距:

    word 文档的页边距、页眉页脚的设置和章节对象有关:

    # 文档页边距设置
    # 获取、设置页面边距
    sec0 = sec[0]  # 获取章节对象
    # 获取页面边距值:(单位为像素)
    print('左边距:',sec0.left_margin)
    # 左边距: 1143000
    print('右边距:',sec0.right_margin)
    # 右边距: 1143000
    print('上边距:',sec0.top_margin)
    # 上边距: 914400
    print('下边距:',sec0.bottom_margin)
    # 下边距: 914400
    print('页眉边距:',sec0.header_distance)
    # 页眉边距: 457200
    print('页脚边距:',sec0.footer_distance)
    # 页脚边距: 457200
    

    3、设置文档页面边距、页面大小:

    # 设置页面高度、宽度
    sec0.page_height = shared.Inches(15)
    sec0.page_width = shared.Inches(10)
    
    # 也可以设置页面的边距:
    sec0.left_margin = shared.Inches(1)
    sec0.right_margin = shared.Inches(1)
    sec0.top_margin = shared.Inches(2)
    sec0.bottom_margin = shared.Inches(2)
    

    设置后的 word 文档截图:

    在这里插入图片描述

    4、设置页眉页脚

    设置页面页脚时,先获取页眉页脚对象

    # 设置页眉
    head0 = sec0.header  # 返回页眉对象
    font0 = sec0.footer  # 返回页脚对象
    print(head0)
    # <docx.section._Header object at 0x000000000B312E08>
    print(font0)
    # <docx.section._Footer object at 0x000000000B312B88>
    

    设置方法:

    "在设置word文档的页眉页脚时,有一个非常重要的是否与前一节相同"
    # 查看页眉是否和上节一直
    print(head0.is_linked_to_previous)  # 默认为 True
    
    # 设置页眉
    "页眉也是一个块级对象,里面也包含了 Paragraph 对象,"
    "所以对齐方式,文字格式设置方式和前文介绍一致。"
    
    print(head0.paragraphs)
    head0_par = head0.paragraphs[0]
    head0_par.add_run('页眉')
    
    # 设置页脚
    font0_par = font0.paragraphs[0]
    font0_par.add_run('页脚')
    # 注: 设置页脚按序列增加的方式暂未找到
    

    页眉页脚设置效果图:
    在这里插入图片描述

    结尾:

    以上就是本篇博客的全部内容,感谢阅读。

    下一篇将会是 python-docx 模块读取 word 文档中各种信息方法的详细介绍,包括段落文本信息、表格文本信息、各类块级元素的格式信息等。

    【Python与Office】专栏

    该专栏会对 Python 的第三方模块,如:xlwt,xlrd,python-docx等,操作 Office 办公软件(Word Excel PPT)的方法进行详细讲解。同时也会搭配一些实例演练,一方面强化知识点的理解与运用,另一方面也希望能起到,引导读者进行思考:如何用 python 提高 offic 办公软件办公效率的作用。

    感兴趣的朋友,可以点个 关注收藏 。如在博客中遇到任何问题或有一些想法、需求,可留言或私信。

    创作不易,你的支持是我最大的动力,感谢 !

    展开全文
  • android 用GridVew实现表格功能Demo

    热门讨论 2013-07-14 17:41:28
    GridView是本身就是个表格,我们见的哇比较多的是用它来显示列表图片,本Demo告诉你如何用GridView制作一个显示文本的表格,相当于MFC的CLIstCtrl控件功能。但是GridbView制作的表格一般都是等宽列的,要实现非等宽...
  • 2、插入表格、设置表格样式、字体样式;3、章节设置:页面大小、边距等;4、设置页眉页脚。1、插入图片、设置大小:上篇博客简单的介绍了插入图片的方法,但是没介绍图片大小的设置方法:# 导入模块fr...

    前言:

    上一篇博客介绍了 python-docx 模块如何 创建 word 文档、设置段落格式、字体格式等 ,本篇博客将对在日常使用 word 文档的其他操作进行介绍。

    主要内容有:

    1、插入图片、设置图片大小;

    2、插入表格、设置表格样式、字体样式;

    3、章节设置:页面大小、边距等;

    4、设置页眉页脚。

    1、插入图片、设置大小:

    上篇博客简单的介绍了插入图片的方法,但是没介绍图片大小的设置方法:

    # 导入模块

    from docx import Document

    # 此模块中包含 docx 中各类单位方法

    from docx import shared

    doc = Document()

    doc.add_heading('python-docx 基础讲解(二)')

    # 在文档中增加图片,并对设置图片大小

    # 当只设置一个方向的长度(宽或高)时,另一方向会自动缩放

    doc.add_picture('1.png',width=shared.Inches(1)) # 按英寸设置

    doc.add_picture('1.png',height=shared.Cm(2)) # 按厘米设置

    # 保存文件

    doc.save('test2.docx')

    注:当只设置图片一个方向的尺寸(宽或高)时,另一方向会自动缩放。

    以上设置后文档截图:

    5f9bdf4ad1003610e7557910362cadac.png

    2、插入表格、设置格式:

    1、在文档中增加表格,并添加文字:

    # 在文档中增加表格,并添加文字

    table1 = doc.add_table(2,3) # 添加一个2行3列的表格,表格样式为None

    "add_table(self, rows, cols, style=None):"

    table1.cell(0,0).text = '0' # 给表格单元格赋值

    # 获取表格对象所有单元格对象列表

    print(table1._cells)

    # ------运行结果------

    # [,

    # ,

    # ,

    # ,

    # ,

    # ]

    # ------运行结果------

    # 对单元格对象设置文字

    for i,cell in enumerate(table1._cells):

    cell.text = str(i)

    注:在word文档中增加表格时,会返回一个 table 对象。table对象中包含单元格 cell 对象,单元格写入数据就是设置 cell 对象的 text 值。

    插入的表格截图:

    29e301d3e45dc999a2c3d47aa7796f0d.png

    2、设置表格样式:

    从增加表格方法:add_table(self, rows, cols, style=None),可以看出在创建表格时,就可以对表格样式进行设置。

    可通过下面的方法获取 word 文档中 默认的表格样式:

    # 获取所有表格样式

    from docx.enum.style import WD_STYLE_TYPE

    styles = doc.styles

    for style in styles:

    if style.type == WD_STYLE_TYPE.TABLE:

    print(style)

    '''

    可设置的表格样式:

    _TableStyle('Normal Table') id: 187730312

    _TableStyle('Table Grid') id: 187730312

    _TableStyle('Light Shading') id: 187730376

    _TableStyle('Light Shading Accent 1') id: 187730312

    _TableStyle('Light Shading Accent 2') id: 187730376

    _TableStyle('Light Shading Accent 3') id: 187730312

    _TableStyle('Light Shading Accent 4') id: 187730376

    _TableStyle('Light Shading Accent 5') id: 187730312

    _TableStyle('Light Shading Accent 6') id: 187730376

    _TableStyle('Light List') id: 187730312

    ...

    内容很多,可以自己尝试运行打印一下

    '''

    以上获取的表格样式,对应word文档里的这些表格样式:

    1a9c16ff2466b45389e390b515b65531.png

    英文也不复杂,大家可以对照一下。

    设置表格样式:

    表格在创建时可及可指定格式:

    doc.add_table(2,3,style ='Table Grid' )

    也可在创建后进行设置:

    # 为表格设置统一样式:

    table1.style = 'Table Grid'

    设置表格样式后表格截图:

    ede3df1fd403204f932e7d9a50c33da9.png

    这样就比较接近日常使用的表格了。

    3、其他表格常用方法:

    # 表格设置自动调整列宽,(默认也为真)

    table1.autofit = True

    # 为表格对象增加列

    table1.add_column(shared.Inches(3)) # 需指定宽度

    "add_column(self, width):"

    # 为表格对象增加行

    table1.add_row() # 只能逐行添加

    "add_row(self):"

    获取表格对象的一些属性:

    # 获取行对象

    row0 = table1.rows[0]

    print(row0)

    # 获取列对象

    col0 = table1.columns[0]

    # 获取表格一行的单元格对象列表

    row0_cells = table1.row_cells(0)

    print(row0_cells)

    # 运行结果

    # [,

    # ,

    # ,

    # ]

    # 获取一列的单元格对象列表

    col_0_cells = table1.column_cells(0)

    print(col_0_cells)

    # 运行结果

    # [,

    # ,

    # ]

    4、设置表格内单元格对齐方式,合并单元格:

    # 设置单元格对齐方式

    # 垂直对齐方式

    from docx.enum.table import WD_ALIGN_VERTICAL

    table1.cell(0,0).vertical_alignment = WD_ALIGN_VERTICAL.TOP

    # 合并单元格

    cell_new = table1.cell(2,0).merge(table1.cell(2,1))

    # 返回一个新单元格对象

    print(cell_new)

    #

    # 要继续合并的话,可用此单元格再次使用 merge 方法

    对表格增加行、列,合并单元格后表格截图:

    66d70adfbd44fce020c140478e2d0ac3.png

    5、设置单元格字体格式:

    单元格内其实也是有 paragraph 对象的,即对单元格内字体设置方式,和对段落中文字格式设置方法一样。

    cell_par = cell_new.paragraphs[0] # 获取到对象

    # 设置对齐方式

    from docx.enum.text import WD_ALIGN_PARAGRAPH

    cell_par.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER

    # 获取 run 对象

    cell_run = cell_new.paragraphs[0].runs[0]

    # 设置字体

    cell_run.font.name = 'Times New Roman'

    from docx.oxml.ns import qn

    cell_run.font.element.rPr.rFonts.set(qn('w:eastAsia'),'楷体')

    # 设置字体颜色

    from docx.shared import RGBColor

    cell_run.font.color.rgb = RGBColor(255,55,55) # 红色

    表格截图:

    8ba8f4a91be43f7cc84fd6b46b817892.png

    3、设置章节、页面设置等:

    章节 也是 word 文档中一个块级元素,相较于段落块级元素它的范围应该更大一点。一般来说:一个 word 文档包含多个章节、一个章节包含多个 run 块级元素。

    一个word文档被建立时至少包含一个章节:

    # word文档中章节 section 对象

    sec = doc.sections

    print(sec) #

    print(len(sec)) # 1

    1、新建章节:

    # 新建一个章节

    doc.add_section()

    print(len(sec)) # 2

    2、获取文档页面边距:

    word 文档的页边距、页眉页脚的设置和章节对象有关:

    # 文档页边距设置

    # 获取、设置页面边距

    sec0 = sec[0] # 获取章节对象

    # 获取页面边距值:(单位为像素)

    print('左边距:',sec0.left_margin)

    # 左边距: 1143000

    print('右边距:',sec0.right_margin)

    # 右边距: 1143000

    print('上边距:',sec0.top_margin)

    # 上边距: 914400

    print('下边距:',sec0.bottom_margin)

    # 下边距: 914400

    print('页眉边距:',sec0.header_distance)

    # 页眉边距: 457200

    print('页脚边距:',sec0.footer_distance)

    # 页脚边距: 457200

    3、设置文档页面边距、页面大小:

    # 设置页面高度、宽度

    sec0.page_height = shared.Inches(15)

    sec0.page_width = shared.Inches(10)

    # 也可以设置页面的边距:

    sec0.left_margin = shared.Inches(1)

    sec0.right_margin = shared.Inches(1)

    sec0.top_margin = shared.Inches(2)

    sec0.bottom_margin = shared.Inches(2)

    设置后的 word 文档截图:

    6a6b15f60850ab2b8e41ad566531ef16.png

    4、设置页眉页脚

    设置页面页脚时,先获取页眉页脚对象:

    # 设置页眉

    head0 = sec0.header # 返回页眉对象

    font0 = sec0.footer # 返回页脚对象

    print(head0)

    #

    print(font0)

    #

    设置方法:

    "在设置word文档的页眉页脚时,有一个非常重要的是否与前一节相同"

    # 查看页眉是否和上节一直

    print(head0.is_linked_to_previous) # 默认为 True

    # 设置页眉

    "页眉也是一个块级对象,里面也包含了 Paragraph 对象,"

    "所以对齐方式,文字格式设置方式和前文介绍一致。"

    print(head0.paragraphs)

    head0_par = head0.paragraphs[0]

    head0_par.add_run('页眉')

    # 设置页脚

    font0_par = font0.paragraphs[0]

    font0_par.add_run('页脚')

    # 注: 设置页脚按序列增加的方式暂未找到

    页眉页脚设置效果图:

    4a5eb77394e59e88e7276494122a4fd9.png

    结尾:

    以上就是本篇博客的全部内容,感谢阅读。

    下一篇将会是 python-docx 模块读取 word 文档中各种信息方法的详细介绍,包括段落文本信息、表格文本信息、各类块级元素的格式信息等。

    该专栏会对 Python 的第三方模块,如:xlwt,xlrd,python-docx等,操作 Office 办公软件(Word Excel PPT)的方法进行详细讲解。同时也会搭配一些实例演练,一方面强化知识点的理解与运用,另一方面也希望能起到,引导读者进行思考:如何用 python 提高 offic 办公软件办公效率的作用。

    感兴趣的朋友,可以点个 关注 或 收藏 。如在博客中遇到任何问题或有一些想法、需求,可留言或私信。

    创作不易,你的支持是我最大的动力,感谢 !

    本文地址:https://blog.csdn.net/zhouz92/article/details/107066709

    希望与广大网友互动??

    点此进行留言吧!

    展开全文
  • 前言:表哥之前已经过一篇freemarker模板导出带表格word详细教程https://blog.csdn.net/erpenggg/article/details/81204061,为什么现在又要写一篇呢。 因为我这次的项目是在手机端导出下载并且查看,用上面的方法...
  • 实体符号表格< table> < tr> < td>align 对齐方式单元格合并th标签 也是单元格标签,比td多的是居中和加粗< thead> < tbody> < tfoot> 标签背景图片background、颜色bgcolor ...
  • 2.内容、图片表格跨页断裂,封边; 3.table并行、并列双边、重边; 4.自动计算页码(总数及每一页),样式、位置、形式完全个性化; 5.页眉页脚,去除浏览默认,自定义内容、样式、位置; 6.保持页脚在页面底部,...
  • 使用jquery的tmpl构建复杂表格

    千次阅读 2014-06-17 16:44:25
    Tmpl提供了几种tag:${}:...{{if }} {{else}}:提供了分支逻辑。{{each}}:提供循环逻辑,$value访问迭代变量。 现在主要介绍利用tmpl构造复杂一点表格,比如说动态加载数据以及单元格合并   打分信息
  • html基础标签 图片、表单、表格、超链接等等
  • Markerdown画部分流程图和复杂表格

    千次阅读 2021-11-18 16:35:03
    或者这样做: 在Excel里把表格建好 保存的时候生成“网页”或“单个网页” 打开方式 在这里插入图片描述 用浏览器打开,用哪个浏览器无所谓 打开后右键单击网页的页面 “查看框架源代码”;注意是框架源代码。或者...
  • python-opencv表格识别

    千次阅读 多人点赞 2020-02-29 16:55:41
    最近学习了一下opencv,做了个简单的小东西,就是识别图片中的表格,识别完成后再把数据写入到csv中保存起来。 环境准备: 下面先说下我们应该要准备下啥环境: 1.python安装完成(笔者python3.7) 2.tesseract...
  • 上一个项目的开发中需要实现从word中读取表格数据的功能,在JAVA社区搜索了很多资料,终于找到了两个相对最佳的方案,因为也得到了不少网友们的帮助,所以不敢独自享用,在此做一个分享。两个方案分别是:一,用POI...
  • 自适应表格单元格

    千次阅读 2016-10-08 09:30:49
    坦率地说,这种方法非常复杂而且问题多多。 在本文中,你将学习如何创建自适应单元格并根据它的内容动态改变它的大小。你可能会想,“那太费事儿了…!” 你错了。:] 在 iOS 8 中,苹果使这个任务变得非常简单...
  • 不规则表格例子:1,11,21,32,1 2,22,3显示:1,11,21,32,1 2,22,3说明:colspan是col span,=2意思是该格占两列。随后的就变成第三列了。例子:1,11,22,21,32,12,3显示:1,11,22,21,32,12,3说明:rowspan和colspan...
  • 如题,介绍如何在VSCode上配置markdown插件(包括:一键插入图片、语法检查、表情包、pdf、预览、表格)。
  • 基于MaskRcnn以及形态学操作的文本图像中表格区域的提取 训练一个可用于检测表格区域的分割网络,在得到网络的输出即文本图像中表格区域后,利用形态学中的开运算提取表格区域中的线段用于后续的操作。 MaskRcnn ...
  • 最近拿到一个需求,需要导出pdf文档,市面上可以实现的方法有很多,经过测试和调研决定使用itext5来实现,话不多说,说干就干。1.依赖导入...2.pdf表格导出实现1.导出pdf// 1.打开文档并设置基本属...
  • 文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。作者:程序IT圈PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取...
  • Java图片处理:网页转图片需求来源于前端同事跟我反馈整天调试布局样式很难受,希望能有服务端网页转图片的方法。 记录一下研究过程。可选方案及评价。最终选取的方案代码细节不足之处可选方案及评价从以下三个方面...
  • MySQL-learning03 复杂一点的查询 DataWhale SQL组队学习 2 练习题-第一部分 product表格: 2.1 创建视图 创建出满足下述三个条件的视图(视图名称为 ViewPractice5_1)。使用product(商品)表作为参照表,假设表...
  • HTML表格边框制作教程

    2021-06-10 16:18:56
    表格以和分别作起始标识符。其中,里有一些必要的参数,为容易理解起见,在这里只介绍本节用到的参数,其他的参数今后将陆续提到。border参数定义表格边框的粗细,记为border=数值,数值取0,1,2,3等整数。width是...
  • 4 公式、图片表格的自动标号和交叉引用 4.1 实现公式的自动标号 4.2 公式的正确排版方式 4.3 采用自动图文集实现格式的复用 4.4 公式的交叉引用和编号更新 4.5 图片表格的自动标号和交叉引用 4.5.1 图片的...
  • [图片说明](https://img-ask.csdn.net/upload/202003/14/1584163751_264479.png)![图片说明](https://img-ask.csdn.net/upload/202003/14/1584163763_152111.png) 上面是现在的表单,想做成下面这样的,有没有...
  • 本文提供了一种常用的LaTeX中英文模板,包含数学公式符号图片表格等,注释中已详细说明,可以根据需要自行编辑修改。
  • 我们在开发过程中对于表格使用频率还是挺高的,使用QT框架开发时候我们使用...特别是对于复杂的表头,使用自带的表头,无论怎么设置都不太可能达到需求。例如我最近接到的一个项目,需求是:我们分析一下这个表格...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,256
精华内容 8,902
关键字:

复杂一点的表格图片