1. 程式人生 > >使用Java編寫Excel傳統課表轉日曆格式

使用Java編寫Excel傳統課表轉日曆格式

今天遇到一個讓她比較苦惱的事情,她手上有一大堆傳統Excel格式的課程安排表,現在想將他們全搞成日曆格式的,她只能手動一個一個搞,效率很低也很無聊,幫她做了個小工具,通過工具實現格式轉換,解放雙手!

原來的資料格式是這樣:
這裡寫圖片描述

轉完的格式是這樣的:
這裡寫圖片描述

思路:
1.原表格中的資料可以抽象成一個類,類中的屬性對應原表格中的列。

package xiaming.chen.domain;

/**
 * Created by xiamingchen on 2017/7/1.
 */
public class Info {
    private String date;
    private String timeBegin;
    private
String course; private int hours; private String teacher; public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getTimeBegin() { return timeBegin; } public void setTimeBegin(String timeBegin) { this
.timeBegin = timeBegin; } public String getCourse() { return course; } public void setCourse(String course) { this.course = course; } public int getHours() { return hours; } public void setHours(int hours) { this.hours = hours; } public
String getTeacher() { return teacher; } public void setTeacher(String teacher) { this.teacher = teacher; } @Override public String toString() { return course + "-" + teacher; } }

2.先將原表格中的資料讀取出來,生成一堆的Info物件。
3.初始化新的Excel,將第一列的課表時間安排寫入。
4.將日期寫入表格,並返回日期總數
5.將每節課的資訊填入表內

package xiaming.chen;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import xiaming.chen.domain.Info;
import xiaming.chen.util.TimeFormatUtil;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 為鴨蛋私人訂製的Excel轉換工具
 */
public class ExcelConvertor {

    private static final String inputFile = "/Users/xiamingchen/Desktop/test.xlsx";
    private static final String outputFile = "/Users/xiamingchen/Downloads/test/test.xlsx";
    private static final int rowBeginNum = 4;

    private static String line1, line2, line3;

    public static void main(String[] args) throws IOException, InvalidFormatException {
        List<Info> infoList = parseInfoFromInputFile(inputFile, rowBeginNum);
        initExcel(outputFile);
        List<String> dateList = writeDateToExcel(outputFile, infoList);
        writeTitleToExcel(outputFile, dateList.size());
        writeInfoToExcel(outputFile, infoList, dateList);
    }

    private static void writeTitleToExcel(String destPath, int columnNum) throws IOException {
        FileInputStream fis = new FileInputStream(destPath);
        XSSFWorkbook wb = new XSSFWorkbook(fis);
        XSSFSheet sheet = wb.getSheetAt(0);

        XSSFRow row1 = sheet.createRow(0);
        createTitleRow(row1, line1, wb);
        XSSFRow row2 = sheet.createRow(1);
        createTitleRow(row2, line2, wb);
        XSSFRow row3 = sheet.createRow(2);
        createTitleRow(row3, line3, wb);

        CellRangeAddress cellRangeAddress1 = new CellRangeAddress(0, 0, 0, columnNum);
        CellRangeAddress cellRangeAddress2 = new CellRangeAddress(1, 1, 0, columnNum);
        CellRangeAddress cellRangeAddress3 = new CellRangeAddress(2, 2, 0, columnNum);
        sheet.addMergedRegion(cellRangeAddress1);
        sheet.addMergedRegion(cellRangeAddress2);
        sheet.addMergedRegion(cellRangeAddress3);

        fis.close();

        FileOutputStream fos = new FileOutputStream(destPath);
        wb.write(fos);
        fos.close();
    }

    private static XSSFRow createTitleRow(XSSFRow row, String value, XSSFWorkbook wb) {
        XSSFCell cell = row.createCell(0);
        cell.setCellValue(value);

        XSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);

        cellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.index);
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        cell.setCellStyle(cellStyle);
        return row;
    }

    private static void writeInfoToExcel(String destPath, List<Info> infoList, List<String> dateList) throws IOException {
        FileInputStream fis = new FileInputStream(destPath);
        XSSFWorkbook wb = new XSSFWorkbook(fis);
        XSSFSheet sheet = wb.getSheetAt(0);

        for (int i=0; i<infoList.size(); ++i) {
            Info info = infoList.get(i);
            int column = dateList.indexOf(info.getDate()) + 1; //+1是因為第一列不是有效列
            int rowOfBegin = getIndexOfBeginTime(info.getTimeBegin(), sheet);
            int rowOfEnd = rowOfBegin + info.getHours() * 2 - 1;
            XSSFRow row = sheet.getRow(rowOfBegin);
            XSSFCell cell = row.createCell(column);
            System.out.println(info.getDate() + " - " + column);
            cell.setCellValue(info.toString());
            CellRangeAddress cellRangeAddress = new CellRangeAddress(rowOfBegin, rowOfEnd, column, column);
            sheet.addMergedRegion(cellRangeAddress);

            XSSFCellStyle cellStyle = wb.createCellStyle();
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            cellStyle.setAlignment(HorizontalAlignment.CENTER);

            cellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.index);
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

            cell.setCellStyle(cellStyle);

            sheet.autoSizeColumn(column, true);
        }

        fis.close();

        FileOutputStream fos = new FileOutputStream(destPath);
        wb.write(fos);
        fos.close();
    }

    private static List<String> writeDateToExcel(String destPath, List<Info> infoList) throws IOException, InvalidFormatException {
        List<String> dateList = new ArrayList<String>();

        FileInputStream fis = new FileInputStream(destPath);
        XSSFWorkbook wb = new XSSFWorkbook(fis);
        XSSFSheet sheet = wb.getSheetAt(0);

        //生成第一行 日期
        int column = 1;//因為第一(0)行無效,所以從第二(1)行開始
        for (int i = 0; i < infoList.size(); ++i) {
            if (dateList.contains(infoList.get(i).getDate())) {
                continue;
            }
            XSSFRow dateRow;
            if (i == 0) {
                dateRow = sheet.createRow(3);
            } else {
                dateRow = sheet.getRow(3);
            }
            XSSFCell dateCell = dateRow.createCell(column);
            dateCell.setCellValue(infoList.get(i).getDate());
            column++;
            dateList.add(infoList.get(i).getDate());
        }
        fis.close();

        FileOutputStream fos = new FileOutputStream(destPath);
        wb.write(fos);
        fos.close();

        return dateList;
    }

    private static int getIndexOfBeginTime(String beginTime, XSSFSheet sheet) {
        int sum = sheet.getLastRowNum();
        for (int i=rowBeginNum; i<=sum; ++i) {
            String eachTime = sheet.getRow(i).getCell(0).getStringCellValue();
            if (beginTime.equals(eachTime)) {
                return i;
            }
        }
        return -1;
    }

    private static void initExcel(String destPath) throws IOException {
        float start = 8.5F;//每天最早八點半開始
        float end = 21.0F;//每天最晚21點結束
        int rowNum = rowBeginNum;//空4行,從第5行開始往下排時間

        FileOutputStream fos = new FileOutputStream(destPath);
        XSSFWorkbook wb = new XSSFWorkbook();
        XSSFSheet sheet = wb.createSheet();

        for (float i = start; i <= end; i = i + 0.5F, rowNum++) {
            XSSFRow row = sheet.createRow(rowNum);
            XSSFCell time = row.createCell(0);
            int minute = (int) (i * 10) % 10;
            String minuteStr = (minute == 5 ? "30" : "00");
            time.setCellValue((int) i + ":" + minuteStr);
        }

        wb.write(fos);
        fos.close();
    }

    private static List<Info> parseInfoFromInputFile(String inputFilePath, int rowBegin) throws IOException {
        List<Info> infoList = new ArrayList<Info>();

        FileInputStream fileInput = new FileInputStream(inputFilePath);
        XSSFWorkbook wb = new XSSFWorkbook(fileInput);
        XSSFSheet sheet = wb.getSheetAt(0);
        int lastRowNum = sheet.getLastRowNum(); //內容的最後一行的行數

        XSSFRow row1 = sheet.getRow(0);
        line1 = row1.getCell(0).getStringCellValue();
        XSSFRow row2 = sheet.getRow(1);
        line2 = row2.getCell(0).getStringCellValue();
        XSSFRow row3 = sheet.getRow(2);
        line3 = row3.getCell(0).getStringCellValue();

        for (int i = rowBegin; i < lastRowNum; ++i) {
            XSSFRow row = sheet.getRow(i);
            if (row.getCell(0).getDateCellValue() == null) { //遇到無效行,結束
                break;
            }

            Info info = new Info();

            Date date = row.getCell(0).getDateCellValue();
            info.setDate(TimeFormatUtil.formatDate(date));

            int hours = (int) row.getCell(3).getNumericCellValue();
            info.setHours(hours);

            String time = row.getCell(1).getStringCellValue();
            String[] times = time.split("-");
            info.setTimeBegin(TimeFormatUtil.formatTime(times[0]));

            String course = row.getCell(2).getStringCellValue();
            info.setCourse(course);

            String teacher = row.getCell(4).getStringCellValue();
            info.setTeacher(teacher);

            infoList.add(info);
        }

        wb.close();
        fileInput.close();

        return infoList;
    }

}

還有一個處理時間和日期的工具類:

package xiaming.chen.util;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by xiamingchen on 2017/7/1.
 */
public class TimeFormatUtil {

    public static String formatDate(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("MM/dd");
        return format.format(date);
    }

    public static String formatTime(String time) {
        int hour = Integer.parseInt(time.split(":")[0]);
        String minute = time.split(":")[1];
        if (hour < 8) { //小時數比8小,那就都是下午的
            hour = hour + 12;
        }
        return hour + ":" + minute;
    }

}