excel的导出与导入

package cn.chn.chen.dev.excel;  

02    

03 import java.lang.annotation.ElementType;  

04 import java.lang.annotation.Retention;  

05 import java.lang.annotation.RetentionPolicy;  

06 import java.lang.annotation.Target;  

07    

08 /**  

09  * <p>  

10  * ExcelAnnotation类主要用于-.  

11  * </p>  

12  * <p>  

13  * 创建时间 2011-4-18 - 下午10:05:47  

14  * </p>  

15  * <blockquote>  

16  * <h4>历史修改记录</h4>  

17  * <ul>  

18  * <li>修改人 修改时间 修改描述  

19  * </ul>  

20  * </blockquote>  

21  * <p>  

22  * copyright cd×××× 2010-2011, all rights reserved.  

23  * </p>  

24  *   

25  * @author IT山人  

26  * @since 1.0  

27  * @version 1.0  

28  */ 

29 @Retention(RetentionPolicy.RUNTIME)  

30 @Target(ElementType.FIELD)  

31 public @interface ExcelAnnotation {  

32      // excel导出时标题显示的名字,如果没有设置Annotation属性,将不会被导出和导入  

33     public String exportName();  

34 } 

ExcelStyle.java;

01 package cn.chn.chen.dev.excel;  

02    

03 import org.apache.poi.hssf.usermodel.HSSFCellStyle;  

04 import org.apache.poi.hssf.usermodel.HSSFFont;  

05 import org.apache.poi.hssf.usermodel.HSSFWorkbook;  

06 import org.apache.poi.hssf.util.HSSFColor;  

07    

08 /**  

09  * <p>  

10  * ExcelStyle类主要用于-excel导出样式控制.  

11  * </p>  

12  * <p>  

13  * 创建时间 2011-4-21 - 下午12:43:11  

14  * </p>  

15  * @author IT山人  

16  */ 

17 public class ExcelStyle {  

18     public static HSSFCellStyle setHeadStyle(HSSFWorkbook workbook,  

19             HSSFCellStyle style) {  

20         style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);  

21         style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);  

22         style.setBorderBottom(HSSFCellStyle.BORDER_THIN);  

23         style.setBorderLeft(HSSFCellStyle.BORDER_THIN);  

24         style.setBorderRight(HSSFCellStyle.BORDER_THIN);  

25         style.setBorderTop(HSSFCellStyle.BORDER_THIN);  

26         style.setAlignment(HSSFCellStyle.ALIGN_CENTER);  

27         // 生成字体  

28         HSSFFont font = workbook.createFont();  

29         font.setColor(HSSFColor.VIOLET.index);  

30         font.setFontHeightInPoints((short) 12);  

31         font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);  

32         // 把字体应用到当前的样样式  

33         style.setFont(font);  

34         return style;  

35    

36     }  

37    

38     public static HSSFCellStyle setbodyStyle(HSSFWorkbook workbook,  

39             HSSFCellStyle style) {  

40         style.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);  

41         style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);  

42         style.setBorderBottom(HSSFCellStyle.BORDER_THIN);  

43         style.setBorderLeft(HSSFCellStyle.BORDER_THIN);  

44         style.setBorderRight(HSSFCellStyle.BORDER_THIN);  

45         style.setBorderTop(HSSFCellStyle.BORDER_THIN);  

46         style.setAlignment(HSSFCellStyle.ALIGN_CENTER);  

47         style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);  

48         // 生成字体  

49         HSSFFont font = workbook.createFont();  

50         font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);  

51         // 把字体应用到当前的样样式  

52         style.setFont(font);  

53         return style;  

54     }  

55 } 
1 ImportExcel.java; 
001 package cn.chn.chen.dev.excel;  

002    

003 import java.io.File;  

004 import java.io.FileInputStream;  

005 import java.lang.reflect.Field;  

006 import java.lang.reflect.Method;  

007 import java.lang.reflect.Type;  

008 import java.text.SimpleDateFormat;  

009 import java.util.ArrayList;  

010 import java.util.Collection;  

011 import java.util.HashMap;  

012 import java.util.Iterator;  

013 import java.util.List;  

014 import java.util.Map;  

015    

016 import org.apache.poi.hssf.usermodel.HSSFSheet;  

017 import org.apache.poi.hssf.usermodel.HSSFWorkbook;  

018 import org.apache.poi.ss.usermodel.Cell;  

019 import org.apache.poi.ss.usermodel.Row;  

020    

021 /**  

022  * <p>  

023  * ImportExcel类主要用于-Excel导入(POI).  

024  * </p>  

025  * <p>  

026  * 创建时间 2011-4-18 - 下午10:33:52  

027  * </p>  

028  * @author IT山人  

029  */ 

030 public class ImportExcel<T> {  

031        

032     Class<T> clazz;  

033        

034     public ImportExcel (Class<T> clazz) {  

035         this.clazz = clazz;  

036     }  

037        

038     public Collection<T> importExcel(File file, String...pattern) {  

039         Collection<T> dist = new ArrayList<T>();  

040         try {  

041             /**  

042              * 类反射得到调用方法  

043              */ 

044             // 得到目标目标类的所有的字段列表    

045             Field[] fields = clazz.getDeclaredFields();  

046             // 将所有标有Annotation的字段,也就是允许导入数据的字段,放入到一个map中  

047             Map<String, Method> fieldMap = new HashMap<String, Method>();  

048             // 循环读取所有字段  

049             for (Field field : fields) {  

050                 // 得到单个字段上的Annotation  

051                 ExcelAnnotation excelAnnotation = field.getAnnotation(ExcelAnnotation.class);  

052                 // 如果标识了Annotationd  

053                 if (excelAnnotation != null) {  

054                     String fieldName = field.getName();  

055                     // 构造设置了Annotation的字段的Setter方法  

056                     String setMethodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);  

057                     // 构造调用的method  

058                     Method setMethod = clazz.getMethod(setMethodName, new Class[] {field.getType()});  

059                     // 将这个method以Annotaion的名字为key来存入  

060                     fieldMap.put(excelAnnotation.exportName(), setMethod);  

061                 }  

062             }  

063                

064             /**  

065              * excel的解析开始  

066              */ 

067             // 将传入的File构造为FileInputStream;  

068             FileInputStream inputStream = new FileInputStream(file);  

069             // 得到工作表  

070             HSSFWorkbook book = new HSSFWorkbook(inputStream);  

071             // 得到第一页  

072             HSSFSheet sheet = book.getSheetAt(0);  

073             // 得到第一面的所有行  

074             Iterator<Row> row = sheet.rowIterator();  

075                

076             /**  

077              * 标题解析  

078              */ 

079             // 得到第一行,也就是标题行  

080             Row titleRow = row.next();  

081             // 得到第一行的所有列  

082             Iterator<Cell> cellTitle = titleRow.cellIterator();  

083             // 将标题的文字内容放入到一个map中  

084             Map<Integer, String> titleMap = new HashMap<Integer, String>();  

085             // 从标题第一列开始  

086             int i = 0;  

087             // 循环标题所有的列  

088             while (cellTitle.hasNext()) {  

089                 Cell cell = (Cell) cellTitle.next();  

090                 String value = cell.getStringCellValue();  

091                 titleMap.put(i, value);  

092                 i++;  

093             }  

094                

095             /**  

096              * 解析内容行  

097              */ 

098             while (row.hasNext()) {  

099                 // 标题下的第一行  

100                 Row rown = row.next();  

101                 // 行的所有列  

102                 Iterator<Cell> cellBody = rown.cellIterator();  

103                 // 得到传入类的实例  

104                 T tObject = clazz.newInstance();  

105                 // 遍历一行的列  

106                 int col = 0;  

107                 while (cellBody.hasNext()) {  

108                     Cell cell = (Cell) cellBody.next();  

109                     // 这里得到此列的对应的标题  

110                     String titleString = titleMap.get(col++);  

111                     // 如果这一列的标题和类中的某一列的Annotation相同,那么则调用此类的的set方法,进行设值  

112                     if (fieldMap.containsKey(titleString)) {  

113                         Method setMethod = fieldMap.get(titleString);  

114                         //得到setter方法的参数  

115                         Type[] types = setMethod.getGenericParameterTypes();  

116                         //只要一个参数  

117                         String xclass = String.valueOf(types[0]);  

118                         //判断参数类型  

119                         if ("class java.lang.String".equals(xclass)) {  

120                             setMethod.invoke(tObject, cell.getStringCellValue());  

121                         } else if ("class java.util.Date".equals(xclass)) {  

122                             setMethod.invoke(tObject, cell.getDateCellValue());  

123                         } else if ("class java.lang.Boolean".equals(xclass)) {  

124                             Boolean boolName = true;  

125                             if ("否".equals(cell.getStringCellValue())) {  

126                                 boolName = false;  

127                             }  

128                             setMethod.invoke(tObject, boolName);  

129                         } else if ("class java.lang.Integer".equals(xclass)) {  

130                             setMethod.invoke(tObject, new Integer(String.valueOf((int)cell.getNumericCellValue())));  

131                         } else if ("class java.lang.Long".equals(xclass)) {  

132                             setMethod.invoke(tObject, new Long(cell.getStringCellValue()));  

133                         } else {  

134                             //  

135                         }  

136                     }  

137                 }  

138                 dist.add(tObject);  

139             }  

140                

141         } catch (Exception e) {  

142             // TODO: handle exception  

143             e.printStackTrace();  

144             return null;  

145         }  

146          return dist;  

147     }  

148        

149     public static void main(String[] args) {  

150         ImportExcel<TestVo> test = new ImportExcel<TestVo>(TestVo.class);  

151         File file = new File("D:\\testOne.xls");  

152         List<TestVo> results = (List<TestVo>) test.importExcel(file);  

153         SimpleDateFormat simpleDateFormat;     

154         simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");       

155         for (TestVo testVo : results) {  

156             System.out.println(testVo.getName() + "\t" + testVo.getSex() + "\t" + simpleDateFormat.format(testVo.getBrith()));  

157         }  

158     }  

159 } 
1 ExcelExport.java; 
001 package cn.chn.chen.dev.excel;  

002    

003 import java.io.File;  

004 import java.io.FileOutputStream;  

005 import java.io.IOException;  

006 import java.io.OutputStream;  

007 import java.lang.reflect.Field;  

008 import java.lang.reflect.Method;  

009 import java.text.SimpleDateFormat;  

010 import java.util.ArrayList;  

011 import java.util.Collection;  

012 import java.util.Date;  

013 import java.util.Iterator;  

014 import java.util.List;  

015    

016 import org.apache.poi.hssf.usermodel.HSSFCell;  

017 import org.apache.poi.hssf.usermodel.HSSFCellStyle;  

018 import org.apache.poi.hssf.usermodel.HSSFRichTextString;  

019 import org.apache.poi.hssf.usermodel.HSSFRow;  

020 import org.apache.poi.hssf.usermodel.HSSFSheet;  

021 import org.apache.poi.hssf.usermodel.HSSFWorkbook;  

022    

023 /**  

024  * <p>  

025  * ExcelExport类主要用于-excel导出(POI).  

026  * </p>  

027  * <p>  

028  * 创建时间 2011-4-21 - 下午12:34:33  

029  * </p>  

030  * @author IT山人  

031  */ 

032 public class ExcelExport<T> {  

033        

034     //格式化日期     

035     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  

036    

037     /**  

038      * <p>  

039      * exportExcel方法-poi Excel导出.  

040      * </p>  

041      * <p>  

042      * 创建人 IT山人 创建时间 2011-4-21 - 下午09:36:21  

043      * </p>  

044      * @param title 工作簿名称  

045      * @param dataset 导出的数据集  

046      * @param out 输出流  

047      */ 

048     @SuppressWarnings("unchecked")  

049     public void exportExcel(String title, Collection<T> dataset, OutputStream out) {  

050         // 声明一个工作薄    

051         try {  

052             //首先检查数据看是否是正确的     

053             Iterator<T> iterator = dataset.iterator();  

054             if (dataset == null || !iterator.hasNext() || title == null || out == null) {  

055                 throw new Exception("传入的数据不对!");  

056             }  

057             //取得实际泛型类     

058             T tObject = iterator.next();  

059             Class<T> clazz = (Class<T>) tObject.getClass();  

060    

061             HSSFWorkbook workbook = new HSSFWorkbook();  

062             // 生成一个表格     

063             HSSFSheet sheet = workbook.createSheet(title);  

064             // 设置表格默认列宽度为20个字节     

065             sheet.setDefaultColumnWidth(20);  

066             // 生成一个样式     

067             HSSFCellStyle style = workbook.createCellStyle();  

068             // 设置标题样式     

069             style = ExcelStyle.setHeadStyle(workbook, style);  

070             // 得到所有字段     

071             Field filed[] = tObject.getClass().getDeclaredFields();  

072    

073             // 标题     

074             List<String> exportfieldtile = new ArrayList<String>();  

075             // 导出的字段的get方法     

076             List<Method> methodObj = new ArrayList<Method>();  

077             // 遍历整个filed     

078             for (int i = 0; i < filed.length; i++) {  

079                 Field field = filed[i];  

080                 ExcelAnnotation excelAnnotation = field.getAnnotation(ExcelAnnotation.class);  

081                 // 如果设置了annottion     

082                 if (excelAnnotation != null) {  

083                     String exprot = excelAnnotation.exportName();  

084                     // 添加到标题     

085                     exportfieldtile.add(exprot);  

086                     // 添加到需要导出的字段的方法     

087                     String fieldname = field.getName();  

088                     String getMethodName = "get" + fieldname.substring(0, 1).toUpperCase() + fieldname.substring(1);  

089                     Method getMethod = clazz.getMethod(getMethodName, new Class[] {});  

090                     methodObj.add(getMethod);  

091                 }  

092             }  

093    

094             // 产生表格标题行     

095             HSSFRow row = sheet.createRow(0);  

096             for (int i = 0; i < exportfieldtile.size(); i++) {  

097                 HSSFCell cell = row.createCell(i);  

098                 cell.setCellStyle(style);  

099                 HSSFRichTextString text = new HSSFRichTextString(exportfieldtile.get(i));  

100                 cell.setCellValue(text);  

101             }  

102                

103             // 循环整个集合     

104             int index = 0;  

105             iterator = dataset.iterator();  

106             while (iterator.hasNext()) {  

107                 //从第二行开始写,第一行是标题     

108                 index++;  

109                 row = sheet.createRow(index);  

110                 T t = (T) iterator.next();  

111                 for (int k = 0; k < methodObj.size(); k++) {  

112                     HSSFCell cell = row.createCell(k);  

113                     Method getMethod = methodObj.get(k);  

114                     Object value = getMethod.invoke(t, new Object[] {});  

115                     String textValue = getValue(value);  

116                     cell.setCellValue(textValue);  

117                 }  

118             }  

119             workbook.write(out);  

120         } catch (Exception e) {  

121             e.printStackTrace();  

122         }  

123     }  

124    

125     /**  

126      * <p>  

127      * getValue方法-cell值处理.  

128      * </p>  

129      * <p>  

130      * 创建人 IT山人 创建时间 2011-4-21 - 下午09:38:31  

131      * </p>  

132      * @param value  

133      * @return  

134      */ 

135     public String getValue(Object value) {  

136         String textValue = "";  

137         if (value == null) {  

138             return textValue;  

139         }  

140         if (value instanceof Boolean) {  

141             boolean bValue = (Boolean) value;  

142             textValue = "是";  

143             if (!bValue) {  

144                 textValue = "否";  

145             }  

146         } else if (value instanceof Date) {  

147             Date date = (Date) value;  

148             textValue = sdf.format(date);  

149    

150         } else {  

151             textValue = value.toString();  

152         }  

153         return textValue;  

154     }     

155    

156     public static void main(String[] args) throws IOException {  

157         OutputStream out = new FileOutputStream("D:\\testOne1.xls");  

158         ExcelExport<TestVo> ex = new ExcelExport<TestVo>();  

159         ImportExcel<TestVo> test = new ImportExcel<TestVo>(TestVo.class);  

160         File file = new File("D:\\testOne.xls");  

161         List<TestVo> results = (List<TestVo>) test.importExcel(file);  

162    

163         ex.exportExcel("测试", results, out);  

164         out.close();  

165     }  

166 } 
1 ImportExcell.java; 
001 package cn.chn.chen.dev.excel;  

002    

003 import java.io.File;  

004 import java.io.FileInputStream;  

005 import java.io.FileNotFoundException;  

006 import java.io.IOException;  

007 import java.text.DecimalFormat;  

008 import java.text.NumberFormat;  

009 import java.util.ArrayList;  

010 import java.util.HashMap;  

011 import java.util.Iterator;  

012 import java.util.List;  

013 import java.util.Map;  

014    

015 import org.apache.commons.lang.StringUtils;  

016 import org.apache.commons.logging.Log;  

017 import org.apache.commons.logging.LogFactory;  

018 import org.apache.poi.hssf.usermodel.HSSFCell;  

019 import org.apache.poi.hssf.usermodel.HSSFDateUtil;  

020 import org.apache.poi.hssf.usermodel.HSSFSheet;  

021 import org.apache.poi.hssf.usermodel.HSSFWorkbook;  

022 import org.apache.poi.ss.usermodel.Cell;  

023 import org.apache.poi.ss.usermodel.Row;  

024    

025 /**  

026  * <p>  

027  * ImportExcell类主要用于-.  

028  * </p>  

029  * <p>  

030  * 创建时间 2011-4-21 - 下午04:45:33  

031  * </p>  

032  * @author IT山人  

033  */ 

034 public class ImportExcell {  

035     private static final Log log = LogFactory.getLog(ImportExcell.class);  

036     /**  

037      * <p>  

038      * readExcel方法-读取excel,行为list,列为Map.  

039      * </p>  

040      * <p>  

041      * 创建人 IT山人 创建时间 2011-4-21 - 下午09:46:33  

042      * </p>  

043      * @param file excel文件  

044      * @return excel表数据集合-行为list,列为Map  

045      */ 

046     public List<Map<String, String>> readExcel(File file) {  

047         log.info("读取excel开始...");  

048         List<Map<String, String>> dataset = new ArrayList<Map<String, String>>();  

049            

050         try {  

051             // 将传入的File构造为FileInputStream;  

052             FileInputStream inputStream = new FileInputStream(file);  

053             // 得到工作表  

054             HSSFWorkbook book  = new HSSFWorkbook(inputStream);  

055             // 得到第一页  

056             HSSFSheet sheet = book.getSheetAt(0);  

057             // 得到第一面的所有行  

058             Iterator<Row> rowIterator = sheet.rowIterator();  

059    

060             // 得到第一行,也就是标题行  

061             @SuppressWarnings("unused")  

062             Row titleRow = rowIterator.next();  

063                

064             while (rowIterator.hasNext()) {  

065                 Row row = rowIterator.next();  

066                 Map<String, String> map = this.creatObjectByRow(row);  

067                 dataset.add(map);  

068             }  

069         } catch (FileNotFoundException e1) {  

070             // TODO Auto-generated catch block  

071             e1.printStackTrace();  

072         } catch (IOException e2) {  

073             // TODO Auto-generated catch block  

074             e2.printStackTrace();  

075         } catch (Exception e) {  

076             // TODO: handle exception  

077         }  

078         log.info("读取excel结束...");  

079         return dataset;  

080     }  

081        

082     /**  

083      * <p>  

084      * creatObjectByRow方法-将每行的数据装载Map中.  

085      * </p>  

086      * <p>  

087      * 创建人 IT山人 创建时间 2011-4-21 - 下午09:48:17  

088      * </p>  

089      * @param row  

090      * @return  

091      */ 

092     private Map<String, String> creatObjectByRow(Row row) {  

093         // 行的所有列  

094         Iterator<Cell> cellBody = row.cellIterator();  

095         // 遍历一行的列  

096         int col = 1;  

097         Map<String, String> map = new HashMap<String, String>();  

098         while (cellBody.hasNext()) {  

099             String field = String.valueOf(col++);  

100             Cell cell = cellBody.next();  

101             if (cell != null) {  

102                 switch (cell.getCellType()) {  

103                     case HSSFCell.CELL_TYPE_STRING:     // 字符  

104                         map.put(field, StringUtils.trim(cell.getStringCellValue()));  

105                         break;  

106                     case HSSFCell.CELL_TYPE_BOOLEAN:    // 布尔  

107                         map.put(field, StringUtils.trim(cell.getStringCellValue()));  

108                         break;  

109                     case HSSFCell.CELL_TYPE_NUMERIC:    // 数字  

110                         if (HSSFDateUtil.isCellDateFormatted(cell)) {// 是否为日期格式  

111                             map.put(field, String.valueOf(cell.getDateCellValue()));  

112                         } else {  

113                             Double cellValue_dob = cell.getNumericCellValue();// 读取cell内数据  

114                             if (String.valueOf(cellValue_dob).length() > 11) { // 如果读取到的是手机号码,需要匹配数字格式  

115                                 DecimalFormat format = (DecimalFormat) NumberFormat.getInstance();  

116                                 //format.applyPattern("00000000000");  

117                                 map.put(field, format.format(cellValue_dob));  

118                             } else { // 如果读取到的是比较短的数字,则去掉尾数(.0)后显示  

119                                 map.put(field, cellValue_dob.toString().substring(0, cellValue_dob.toString().length() - 2));  

120                             }  

121                         }  

122                         break;  

123                     case HSSFCell.CELL_TYPE_FORMULA:    // 公式   

124                         map.put(field, String.valueOf(cell.getNumericCellValue()));  

125                         break;  

126                     case HSSFCell.CELL_TYPE_BLANK:      // 空  

127                         map.put(field, StringUtils.trim(cell.getStringCellValue()));  

128                         break;  

129                     case HSSFCell.CELL_TYPE_ERROR:      // 异常  

130                         map.put(field, StringUtils.trim(cell.getStringCellValue()));  

131                         break;  

132                     default:  

133                         map.put(field, StringUtils.trim(cell.getStringCellValue()));  

134                         break;  

135                 }  

136             }  

137         }  

138         return map;  

139     }  

140    

141     public static void main(String[] args) {  

142         // TODO Auto-generated method stub  

143         ImportExcell inport = new ImportExcell();  

144         File file = new File("D:\\testOne.xls");  

145         List<Map<String, String>> mapList = inport.readExcel(file);  

146         for (Map<String, String> map : mapList) {  

147 //          Iterator<Entry<String, String>> iterator = map.entrySet().iterator();  

148 //          while (iterator.hasNext()) {  

149 //              Map.Entry<String, String> entry = iterator.next();  

150 //              String key = entry.getKey();  

151 //              String value = entry.getValue();  

152 //              System.out.println("key:" + key + "\tvalue:" + value);  

153 //          }  

154             TestVo t = new TestVo();  

155             t.setName(map.get("1"));  

156             System.out.println(t.getName());  

157         }  

158     }  

159 } 
1 TestVo.java; 
01 public class TestVo {  

02        

03     @ExcelAnnotation(exportName="姓名")  

04     private String name;  

05        

06     @ExcelAnnotation(exportName="性别")  

07     private Integer sex;  

08        

09     @ExcelAnnotation(exportName="出生年月")  

10     private Date brith;  

11    

12     /**  

13      * @return 返回 name  

14      */ 

15     public String getName() {  

16         return name;  

17     }  

18    

19     /**  

20      * @param name 设置 name  

21      */ 

22     public void setName(String name) {  

23         this.name = name;  

24     }  

25    

26     /**  

27      * @return 返回 sex  

28      */ 

29     public Integer getSex() {  

30         return sex;  

31     }  

32    

33     /**  

34      * @param sex 设置 sex  

35      */ 

36     public void setSex(Integer sex) {  

37         this.sex = sex;  

38     }  

39    

40     /**  

41      * @return 返回 brith  

42      */ 

43     public Date getBrith() {  

44         return brith;  

45     }  

46    

47     /**  

48      * @param brith 设置 brith  

49      */ 

50     public void setBrith(Date brith) {  

51         this.brith = brith;  

52     }  

53        

54 } 


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值