使用java和Velocity建立html複雜的table

1、問題介紹

在工做中遇到過這樣的的需求,要用java生成一個以下樣式的html表格,這個樣例只是一個簡單的舉例子,還可能更復雜。最後選擇velocity模版引擎實現,表格最後是什麼樣子,只有得到數據以後才能肯定,因此在代碼中動態建立表格。
複雜樣式html

2、原理介紹

一、在html中,表格的標籤是<table>,行的標籤是<tr>,列的標籤是<td>。從這些標籤,能夠看出,表格->行->列->單元格,是對錶格的細粒度的控制。
二、在標籤<td>中,有rowspancolspan兩個屬性,分別控制着單元格向右和向下佔據幾個單元格,對於默認值、0和1,效果都是同樣的,都只是佔據本身的單元格,不會佔據其餘的單元格。複雜表格的建立,主要就是細粒度的控制這個2屬性。
三、就像在(1)裏面介紹的,爲了細粒度的控制,html抽象出了表格,行,列的標籤。基於java,咱們也能夠抽象出類Table表示表格,抽象出類Cell表示單元格。在類Table中用一個二維數據容納類Cell,這樣就能夠完整的表示一個表格了。
四、類Cell中有四個基本的字段java

private String message = "";  
private int rowspan = 0;  
private int colspan = 0;  
private boolean visiable = true;
public Cell(String message, int rowspan, int colspan, boolean visiable) {
    this.message = message;
    this.rowspan = rowspan;
    this.colspan = colspan;
    this.visiable = visiable;
}

message字段表示要顯示的文本.
rowspan字段表示<td>標籤中rowspan屬性.
colspan字段表示<td>標籤中colspan屬性.
visiable字段表示是否顯示<td>標籤
四、類Table中有三個基本的字段apache

// 建立表格的行數
private int rows = 0;
// 建立表格的列數
private int cols = 0;
// 二維數組
private Cell[][]  cells = null;

public Table(int rows, int cols) {
    this.rows = rows;
    this.cols = cols;
    this.cells = new Cell[rows][cols];
    init(rows, cols);
}

private void init(int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            cells[i][j] = new Cell("A", 1, 1, true);
        }
    }
}

在建立Table類的時候要傳行數rows、列數cols,用來初始化表格。數組

public void addCell(Cell cell, int row, int col) {
    int rowIndex = row - 1;
    int colIndex = col - 1;
    int rowSize = rowIndex + cell.getRowspan();
    int colSize = colIndex + cell.getColspan();
    for (int i = rowIndex; i < rowSize; i++) {
        for (int j = colIndex; j < colSize; j++) {
            cells[i][j].setVisiable(false);
            cells[i][j].setMessage("noVisiable");
        }
    }
    cells[rowIndex][colIndex] = cell;
}

這個addCell方法是類Table的核心方法,處理添加的Cell。row和col參數(都從1開始),指定了Cell的起始位置。處理的邏輯:從Cell的起始位置開始,按照rowspan和colspan的值,分別向右和向下的Cell的visiable屬性設置爲false(不顯示),那麼在velocity渲染的時候就不會顯示這些單元格。添加的Cell就能佔據這些不會顯示的單元格的位置。測試

3、完整代碼

一、Table類this

public class Table {
    // 建立表格的行數
    private int rows = 0;
    // 建立表格的列數
    private int cols = 0;
    // 二維數組
    private Cell[][]  cells = null;

    public Table(int rows, int cols) {
        this.rows = rows;
        this.cols = cols;
        this.cells = new Cell[rows][cols];
        init(rows, cols);
    }

    private void init(int rows, int cols) {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                cells[i][j] = new Cell("A", 1, 1, true);
            }
        }
    }

    public void addCell(Cell cell, int row, int col) {
        int rowIndex = row - 1;
        int colIndex = col - 1;
        int rowSize = rowIndex + cell.getRowspan();
        int colSize = colIndex + cell.getColspan();
        for (int i = rowIndex; i < rowSize; i++) {
            for (int j = colIndex; j < colSize; j++) {
                cells[i][j].setVisiable(false);
                cells[i][j].setMessage("noVisiable");
            }
        }
        cells[rowIndex][colIndex] = cell;
    }

    public int getRows() {
        return rows;
    }

    public void setRows(int rows) {
        this.rows = rows;
    }

    public int getCols() {
        return cols;
    }

    public void setCols(int cols) {
        this.cols = cols;
    }

    public Cell getCell(int row, int col) {
        return cells[row - 1][col - 1];
    }

    public void setCells(Cell[][] cells) {
        this.cells = cells;
    }
}

二、Cell類spa

public class Cell {

    private String message = "";
    private int rowspan = 0;
    private int colspan = 0;
    private boolean visiable = true;

    public Cell(String message, int rowspan, int colspan, boolean visiable) {
        this.message = message;
        this.rowspan = rowspan;
        this.colspan = colspan;
        this.visiable = visiable;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public int getRowspan() {
        return rowspan;
    }

    public void setRowspan(int rowspan) {
        this.rowspan = rowspan;
    }

    public int getColspan() {
        return colspan;
    }

    public void setColspan(int colspan) {
        this.colspan = colspan;
    }

    public boolean isVisiable() {
        return visiable;
    }

    public void setVisiable(boolean visiable) {
        this.visiable = visiable;
    }
}

三、velocitycode

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>table</title>
</head>
<body>
<table border="1">
    #foreach($row in [1..$table.rows])
        <tr>
            #foreach($col in [1..$table.cols])
                #set ($cell = $table.getCell($row, $col))
                #if($cell.visiable)
                    <td rowspan="$cell.rowspan" colspan="$cell.colspan" align="center">$cell.message</td>
                #end
            #end
        </tr>
    #end

</table>
</body>
</html>

四、測試類htm

public static void main(String[] args) {
    Table table = new Table(4, 7);

    table.addCell(new Cell("sample", 2, 2, true), 2, 2);

    VelocityEngine ve = new VelocityEngine();
    ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
    ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
    ve.init();

    Template t = ve.getTemplate("example.vm");
    VelocityContext ctx = new VelocityContext();
    ctx.put("table", table);

    StringWriter sw = new StringWriter();
    t.merge(ctx, sw);

    System.out.println(sw.toString());
}

五、簡單的效果圖
例子blog

4、後記

這裏只是簡單的介紹了一種實現複雜表格的思路,舉例子中用的java和velocity,其實不限於這2者,單元格的屬性也能夠擴展。還能夠看其餘的文章:
http://www.easyjf.com/blog/html/20080109/1015823.html
https://www.javaworld.com/article/2077810/open-source-tools/complex-html-tables-made-easy-with-apache-velocity.html

相關文章
相關標籤/搜索