最近公司需要開發一個公司內部使用的快遞下單系統,給我的開發任務中有一個生成電子面單功能,為了下單時更方便,利用此功能使用快遞公司給我們的印表機直接列印出電子面單,剛接到這個任務時我想這應該很簡單,不就是做一個表格列印出來嗎,原本以為使用excel或者word等工具直接生成一個文檔,後來經理說不用ex ...
最近公司需要開發一個公司內部使用的快遞下單系統,給我的開發任務中有一個生成電子面單功能,為了下單時更方便,利用此功能使用快遞公司給我們的印表機直接列印出電子面單,剛接到這個任務時我想這應該很簡單,不就是做一個表格列印出來嗎,原本以為使用excel或者word等工具直接生成一個文檔,後來經理說不用excel和word工具,讓用Java直接生成電子面單,剛開始有點懵,因為不知道Java還有繪圖功能,因此在網上學習了一下Java怎樣繪圖,索性直接開乾。
廢話不多說直接上代碼。
一、 首先是生成條碼工具類,此類是生成快遞單號條碼。
SFBarCodeGenerateUtil.java
1 package testNetty.wu; 2 3 import java.awt.Color; 4 import java.awt.Graphics; 5 import java.awt.Image; 6 import java.awt.image.BufferedImage; 7 import java.io.BufferedInputStream; 8 import java.io.BufferedOutputStream; 9 import java.io.File; 10 import java.io.FileInputStream; 11 import java.io.FileNotFoundException; 12 import java.io.FileOutputStream; 13 import java.io.OutputStream; 14 import java.util.ArrayList; 15 import java.util.List; 16 import java.util.regex.Pattern; 17 18 import javax.imageio.ImageIO; 19 20 import org.apache.log4j.Logger; 21 22 23 import com.sun.image.codec.jpeg.JPEGCodec; 24 import com.sun.image.codec.jpeg.JPEGImageEncoder; 25 26 /** 27 * 順豐速運條碼生成工具<br/> 28 * 採用 code128c編碼規則<br/> 29 * <pre> 30 * CODE128C:[00]-[99]的數字對集合,共100個 31 * 即只能表示偶數位長度的數字 32 * </pre> 33 * @author wu 34 * @version 1.0 35 * @Time 2017/03/29 36 * */ 37 public class SFBarCodeGenerateUtil { 38 39 private static final Logger logger = Logger.getLogger(SFBarCodeGenerateUtil.class.getSimpleName()); 40 41 /**圖片格式 jpg 格式*/ 42 public static final String PICTURE_JPG = "JPG"; 43 /**圖片格式 png 格式*/ 44 public static final String PICTURE_PNG = "PNG"; 45 /**圖片格式 gif 格式*/ 46 public static final String PICTURE_GIF = "GIF"; 47 48 /** code128編碼字元集 二維數組*/ 49 private static String[][] code128 = { 50 { " ", " ", "00", "212222", "11011001100" }, 51 { "!", "!", "01", "222122", "11001101100" }, 52 { "\"", "\"", "02", "222221", "11001100110" }, 53 { "#", "#", "03", "121223", "10010011000" }, 54 { "$", "$", "04", "121322", "10010001100" }, 55 { "%", "%", "05", "131222", "10001001100" }, 56 { "&", "&", "06", "122213", "10011001000" }, 57 { "'", "'", "07", "122312", "10011000100" }, 58 { "(", "(", "08", "132212", "10001100100" }, 59 { ")", ")", "09", "221213", "11001001000" }, 60 { "*", "*", "10", "221312", "11001000100" }, 61 { "+", "+", "11", "231212", "11000100100" }, 62 { ",", ",", "12", "112232", "10110011100" }, 63 { "-", "-", "13", "122132", "10011011100" }, 64 { ".", ".", "14", "122231", "10011001110" }, 65 { "/", "/", "15", "113222", "10111001100" }, 66 { "0", "0", "16", "123122", "10011101100" }, 67 { "1", "1", "17", "123221", "10011100110" }, 68 { "2", "2", "18", "223211", "11001110010" }, 69 { "3", "3", "19", "221132", "11001011100" }, 70 { "4", "4", "20", "221231", "11001001110" }, 71 { "5", "5", "21", "213212", "11011100100" }, 72 { "6", "6", "22", "223112", "11001110100" }, 73 { "7", "7", "23", "312131", "11101101110" }, 74 { "8", "8", "24", "311222", "11101001100" }, 75 { "9", "9", "25", "321122", "11100101100" }, 76 { ":", ":", "26", "321221", "11100100110" }, 77 { ";", ";", "27", "312212", "11101100100" }, 78 { "<", "<", "28", "322112", "11100110100" }, 79 { "=", "=", "29", "322211", "11100110010" }, 80 { ">", ">", "30", "212123", "11011011000" }, 81 { "?", "?", "31", "212321", "11011000110" }, 82 { "@", "@", "32", "232121", "11000110110" }, 83 { "A", "A", "33", "111323", "10100011000" }, 84 { "B", "B", "34", "131123", "10001011000" }, 85 { "C", "C", "35", "131321", "10001000110" }, 86 { "D", "D", "36", "112313", "10110001000" }, 87 { "E", "E", "37", "132113", "10001101000" }, 88 { "F", "F", "38", "132311", "10001100010" }, 89 { "G", "G", "39", "211313", "11010001000" }, 90 { "H", "H", "40", "231113", "11000101000" }, 91 { "I", "I", "41", "231311", "11000100010" }, 92 { "J", "J", "42", "112133", "10110111000" }, 93 { "K", "K", "43", "112331", "10110001110" }, 94 { "L", "L", "44", "132131", "10001101110" }, 95 { "M", "M", "45", "113123", "10111011000" }, 96 { "N", "N", "46", "113321", "10111000110" }, 97 { "O", "O", "47", "133121", "10001110110" }, 98 { "P", "P", "48", "313121", "11101110110" }, 99 { "Q", "Q", "49", "211331", "11010001110" }, 100 { "R", "R", "50", "231131", "11000101110" }, 101 { "S", "S", "51", "213113", "11011101000" }, 102 { "T", "T", "52", "213311", "11011100010" }, 103 { "U", "U", "53", "213131", "11011101110" }, 104 { "V", "V", "54", "311123", "11101011000" }, 105 { "W", "W", "55", "311321", "11101000110" }, 106 { "X", "X", "56", "331121", "11100010110" }, 107 { "Y", "Y", "57", "312113", "11101101000" }, 108 { "Z", "Z", "58", "312311", "11101100010" }, 109 { "[", "[", "59", "332111", "11100011010" }, 110 { "\\", "\\", "60", "314111", "11101111010" }, 111 { "]", "]", "61", "221411", "11001000010" }, 112 { "^", "^", "62", "431111", "11110001010" }, 113 { "_", "_", "63", "111224", "10100110000" }, 114 { "NUL", "`", "64", "111422", "10100001100" }, 115 { "SOH", "a", "65", "121124", "10010110000" }, 116 { "STX", "b", "66", "121421", "10010000110" }, 117 { "ETX", "c", "67", "141122", "10000101100" }, 118 { "EOT", "d", "68", "141221", "10000100110" }, 119 { "ENQ", "e", "69", "112214", "10110010000" }, 120 { "ACK", "f", "70", "112412", "10110000100" }, 121 { "BEL", "g", "71", "122114", "10011010000" }, 122 { "BS", "h", "72", "122411", "10011000010" }, 123 { "HT", "i", "73", "142112", "10000110100" }, 124 { "LF", "j", "74", "142211", "10000110010" }, 125 { "VT", "k", "75", "241211", "11000010010" }, 126 { "FF", "I", "76", "221114", "11001010000" }, 127 { "CR", "m", "77", "413111", "11110111010" }, 128 { "SO", "n", "78", "241112", "11000010100" }, 129 { "SI", "o", "79", "134111", "10001111010" }, 130 { "DLE", "p", "80", "111242", "10100111100" }, 131 { "DC1", "q", "81", "121142", "10010111100" }, 132 { "DC2", "r", "82", "121241", "10010011110" }, 133 { "DC3", "s", "83", "114212", "10111100100" }, 134 { "DC4", "t", "84", "124112", "10011110100" }, 135 { "NAK", "u", "85", "124211", "10011110010" }, 136 { "SYN", "v", "86", "411212", "11110100100" }, 137 { "ETB", "w", "87", "421112", "11110010100" }, 138 { "CAN", "x", "88", "421211", "11110010010" }, 139 { "EM", "y", "89", "212141", "11011011110" }, 140 { "SUB", "z", "90", "214121", "11011110110" }, 141 { "ESC", "{", "91", "412121", "11110110110" }, 142 { "FS", "|", "92", "111143", "10101111000" }, 143 { "GS", "},", "93", "111341", "10100011110" }, 144 { "RS", "~", "94", "131141", "10001011110" }, 145 { "US", "DEL", "95", "114113", "10111101000" }, 146 { "FNC3", "FNC3", "96", "114311", "10111100010" }, 147 { "FNC2", "FNC2", "97", "411113", "11110101000" }, 148 { "SHIFT", "SHIFT", "98", "411311", "11110100010" }, 149 { "CODEC", "CODEC", "99", "113141", "10111011110" }, 150 { "CODEB", "FNC4", "CODEB", "114131", "10111101110" }, 151 { "FNC4", "CODEA", "CODEA", "311141", "11101011110" }, 152 { "FNC1", "FNC1", "FNC1", "411131", "11110101110" }, 153 { "StartA", "StartA", "StartA", "211412", "11010000100" }, 154 { "StartB", "StartB", "StartB", "211214", "11010010000" }, 155 { "StartC", "StartC", "StartC", "211232", "11010011100" }, 156 { "Stop", "Stop", "Stop", "2331112", "1100011101011" }, 157 }; 158 159 /** 160 * 生產Code128的條形碼的code 161 * @param barCode 生成條碼的數字型大小碼 162 * @return 163 */ 164 private static String getCode(String barCode) { 165 String rtnCode = "";// 返回的參數 166 List<Integer> rtnCodeNumb = new ArrayList<Integer>();// 2截取位的組合 167 int examine = 105; // 首位 168 // 編碼不能是奇數 169 if (!((barCode.length() & 1) == 0)) 170 return ""; 171 while (barCode.length() != 0) { 172 int temp = 0; 173 try { 174 // Code128 編碼必須為數字 175 temp = (Integer) Integer.valueOf(barCode.substring(0, 2)); 176 } catch (Exception e) { 177 e.printStackTrace(); 178 return ""; 179 } 180 // 獲得條紋 181 rtnCode += getValue(barCode, barCode.substring(0, 2), temp); 182 rtnCodeNumb.add(temp); 183 // 條碼截取2個就需要去掉用過的前二位 184 barCode = barCode.substring(2); 185 } 186 if (rtnCodeNumb.size() == 0) { 187 return ""; 188 } 189 rtnCode = getValue(examine) + rtnCode; // 獲取開始位 190 for (int i = 0; i != rtnCodeNumb.size(); i++) { 191 examine += rtnCodeNumb.get(i) * (i + 1); 192 } 193 examine = examine % 103; // 獲得校驗位 194 rtnCode += getValue(examine); // 獲取校驗位 195 rtnCode += "1100011101011"; // 結束位 196 return rtnCode; 197 } 198 199 /** 200 * 根據編號獲得條紋 201 * 202 * @param encode 203 * @param p_Value 204 * @param p_SetID 205 * @return 206 */ 207 private static String getValue(String encode, String p_Value, int p_SetID) { 208 return code128[p_SetID][4]; 209 } 210 211 /** 212 * 根據編號獲得條紋 213 * @param p_CodeId 214 * @return 215 */ 216 private static String getValue(int p_CodeId) { 217 return code128[p_CodeId][4]; 218 } 219 220 // 條碼的高度像素數 221 private static int m_nImageHeight = 40; 222 223 /** 224 * 生成條碼 225 * @param barString 條碼模式字元串 226 * @param path 生成條碼圖片的路徑 227 */ 228 private static boolean kiCode128C(String barString, String path) { 229 OutputStream out = null; 230 try { 231 File myPNG = new File(path); 232 out = new FileOutputStream(myPNG); 233 int nImageWidth = 0; 234 char[] cs = barString.toCharArray(); 235 for (int i = 0; i != cs.length; i++) { 236 nImageWidth = cs.length; 237 } 238 BufferedImage bi = new BufferedImage(nImageWidth, m_nImageHeight, 239 BufferedImage.TYPE_INT_RGB); 240 Graphics g = bi.getGraphics(); 241 for (int i = 0; i < cs.length; i++) { 242 if ("1".equals(cs[i] + "")) { 243 g.setColor(Color.BLACK); 244 g.fillRect(i, 0, 1, m_nImageHeight); 245 } else { 246 g.setColor(Color.WHITE); 247 g.fillRect(i, 0, 1, m_nImageHeight); 248 } 249 } 250 JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); 251 encoder.encode(bi); 252 return true; 253 } catch (FileNotFoundException fe) { 254 logger.error("系統找不到指定路徑!!" + path, fe); 255 return false; 256 } catch (Exception e) { 257 e.printStackTrace(); 258 } finally { 259 try { 260 if (out != null) 261 out.close(); 262 } catch (Exception e2) { 263 e2.printStackTrace(); 264 } 265 } 266 return false; 267 } 268 269 /** 270 * 生成條形碼<br/> 271 * 條碼是圖片格式(JPG、PNG、GIF) 272 * @param wayBillNo 273 * 運單號 274 * @param generatePathName 275 * 生成條形碼路徑及名稱 276 * @param width 277 * 條碼圖片寬度 278 * @param height 279 * 條碼圖片高度 280 * @param picTyp 281 * 圖片格式<br/> 282 * JPG、PNG、GIF三種圖片類型選擇 283 * @return boolean類型值 284 * true 生成成功,false 生成失敗 285 * */ 286 public static boolean generateBarCode(String wayBillNo, String generatePathName, int width, 287 int height, String picTyp){ 288 //只能是數字 289 if (!Pattern.matches("[0-9]+", wayBillNo)) { 290 logger.error("生成CODE128C條碼只能是0~9的數字不能有其他字元!!"); 291 //運單號長度只能是偶數 292 } else if (wayBillNo.length() % 2 != 0) { 293 logger.error("生成CODE128C條碼的長度只能是偶數!!"); 294 //生成條碼 295 } else if (kiCode128C(getCode(wayBillNo), generatePathName)){ 296 /** 297 * 設置條碼圖片的尺寸 298 * */ 299 BufferedInputStream bis = null; 300 BufferedOutputStream out = null; 301 try { 302 File sfFile = new File(generatePathName); 303 if (sfFile.isFile() && sfFile.exists()) { 304 //讀取圖片 305 bis = new BufferedInputStream(new FileInputStream(generatePathName)); 306 //轉換成圖片對象 307 Image bi = ImageIO.read(bis); 308 //構建圖片流 設置圖片寬和高 309 BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 310 //繪製改變尺寸後的圖 311 tag.getGraphics().drawImage(bi, 0, 0,width, height, null); 312 //保存圖片 313 out = new BufferedOutputStream(new FileOutputStream(generatePathName)); 314 ImageIO.write(tag, picTyp,out); 315 out.flush(); 316 } 317 } catch (Exception e) { 318 e.printStackTrace(); 319 } finally { 320 try { 321 if (out != null) 322 out.close(); 323 if (bis != null) 324 bis.close(); 325 } catch (Exception e2) { 326 e2.printStackTrace(); 327 } 328 } 329 logger.info("條碼生成成功. " + generatePathName + " 像素:" + width + "*" + height); 330 return true; 331 } 332 logger.error("條碼生成失敗!"); 333 return false; 334 } 335 336 }
二、其次是生成電子面單表格類,包含條碼、單號、寄件人和收件人信息。
SFOrderGenerateUtil.java
1 package testNetty.wu; 2 3 import java.awt.BasicStroke; 4 import java.awt.Color; 5 import java.awt.Font; 6 import java.awt.Graphics2D; 7 import java.awt.Image; 8 import java.awt.RenderingHints; 9 import java.awt.image.BufferedImage; 10 import java.io.BufferedInputStream; 11 import java.io.BufferedOutputStream; 12 import java.io.ByteArrayOutputStream; 13 import java.io.File; 14 import java.io.FileInputStream; 15 import java.io.FileNotFoundException; 16 import java.io.FileOutputStream; 17 import java.io.IOException; 18 19 import javax.imageio.ImageIO; 20 21 import org.apache.commons.io.FileUtils; 22 import org.apache.log4j.Logger; 23 24 import com.sun.image.codec.jpeg.JPEGCodec; 25 import com.sun.image.codec.jpeg.JPEGEncodeParam; 26 import com.sun.image.codec.jpeg.JPEGImageEncoder; 27 28 /** 29 * 生成電子面單圖片工具 30 * @author wu 31 * @version 1.0 32 * @time 2017/04/25 33 * */ 34 public class SFOrderGenerateUtil { 35 36 private static final Logger logger = Logger.getLogger(SFOrderGenerateUtil.class.getSimpleName()); 37 38 //圖片的寬度 39 public static final int IMG_WIDTH = 1198; 40 //圖片的寬度 41 public static final int IMG_HEIGHT = 1800; 42 //LOGO的寬度 43 public static final int LOGO_WIDTH = 240; 44 //LOGO高度 45 public static final int LOGO_HEIGHT = 100; 46 //LOGO客服電話的寬度 47 public static final int LOGO_TEL_WIDTH = 220; 48 //LOGO客服電話高度 49 public static final int LOGO_TEL_HEIGHT = 84; 50 51 //Logo路徑 52 public static final String LOGO_PATH = "C:\\Users\\Administrator\\Desktop\\expressLogo\\logoSC.png"; 53 //Logo客服電話 54 public static final String LOGO_TEL_PATH = "C:\\Users\\Administrator\\Desktop\\expressLogo\\sf_Tel.png";; 55 56 57 public static BufferedImage image; 58 public static void createImage(String fileLocation) { 59 FileOutputStream fos = null; 60 BufferedOutputStream bos = null; 61 try { 62 fos = new FileOutputStream(fileLocation); 63 bos = new BufferedOutputStream(fos); 64 JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos); 65 encoder.encode(image); 66 } catch (Exception e) { 67 e.printStackTrace(); 68 } finally { 69 try { 70 if (bos != null) bos.close(); 71 if (fos != null) fos.close(); 72 } catch (Exception e2) { 73 e2.printStackTrace(); 74 } 75 } 76 } 77 78 /** 79 * 生成訂單圖片 80 * @param orderPath 81 * 生成訂單存放路徑 82 * @param printTyp 83 * 訂單列印類型 1:A4紙列印 2:熱敏紙列印 84 * @param orderParam 85 * 生成訂單所需的參數對象 86 * @param isCompress 87 * 是否需要根據輸入寬高壓縮圖片 88 * <pre> 89 * isCompress 為ture時 所輸入的寬高才起作用 90 * </pre> 91 * @param imgWidth 92 * 圖片寬度 93 * @param imgHeidht 94 * 圖片高度 95 * @author Administrator 96 * @return 97 * 98 * */ 99 public static boolean generateOrders(String orderPath, SfPrintOrderParam orderParam, String printTyp, boolean isCompress, int imgWidth, int imgHeidht){ 100 if (null == orderParam) 101 return false; 102 int startHeight = 0; //表格的起始高度 103 int startWidth = 0; //表格的起始寬度 104 try { 105 if (orderParam.getSubMailNos().size() == 0 || orderParam.getSubMailNos().isEmpty()) { 106 generateParentOrder(orderPath, orderParam, printTyp, isCompress, imgWidth, imgHeidht); 107 return true; 108 } else { 109 String picPath = orderPath; 110 File mk = new File(picPath + orderParam.getMailNo()); 111 if (mk.exists()){ 112 FileUtils.deleteDirectory(mk); 113 } 114 for (int<