excel 图表
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.13</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.13</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>3.13</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>ooxml-schemas</artifactId> <version>1.1</version> </dependency>
window.open(contextPath+'/supplier/operateQuality/upload.do?supplierId='+
supplierIdArrs+'&&productId='+productIdArr+'&&orderNo='+orderNo+'&&time='+month)
//导出普通的excel
XSSFWorkbook workBook = new XSSFWorkbook(); XSSFSheet sheet = workBook.createSheet(); String[] cellTitle = {"ID", "供应商订单号", "供应商名称", "车型", "服务类型", "下单时间", "航班时间", "计划用车时间", "开始服务时间", "结束服务时间", "晚于开始服务时间", "开始服务*小时后未结束"}; workBook.setSheetName(3, "List"); // 创建表格标题行 第一行 XSSFRow titleRow = sheet.createRow(0); //设置标题样式 XSSFCellStyle cellStyle = workBook.createCellStyle(); Font headerFont = workBook.createFont(); /* adding heading style */ cellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex()); cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); cellStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN); //下边框 cellStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN);//左边框 cellStyle.setBorderTop(XSSFCellStyle.BORDER_THIN);//上边框 cellStyle.setBorderRight(XSSFCellStyle.BORDER_THIN);//右边框 cellStyle.setWrapText(true); headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD); cellStyle.setFont(headerFont); for (int i = 0; i < cellTitle.length; i++) { XSSFCell cell = titleRow.createCell(i); cell.setCellStyle(cellStyle); //第一个参数代表列id(从0开始),第2个参数代表宽度值 sheet.setColumnWidth(i, 3800); cell.setCellValue(cellTitle[i]); } int j=1; for (int i = 0; i < supplierQualityPageData.getRows().size(); i++) { XSSFRow row = sheet.createRow(j++); row.createCell(0).setCellValue(i+1); row.createCell(1).setCellValue(supplierQualityPageData.getRows().get(i).getOrderNo()); row.createCell(2).setCellValue(supplierQualityPageData.getRows().get(i).getSupplierName()); row.createCell(3).setCellValue(supplierQualityPageData.getRows().get(i).getProductName()); row.createCell(4).setCellValue(supplierQualityPageData.getRows().get(i).getDirectionType()); row.createCell(5).setCellValue(supplierQualityPageData.getRows().get(i).getOrderTm()); row.createCell(6).setCellValue(supplierQualityPageData.getRows().get(i).getFlightDate()); row.createCell(7).setCellValue(supplierQualityPageData.getRows().get(i).getReservedTime()); row.createCell(8).setCellValue(supplierQualityPageData.getRows().get(i).getStartTime()); row.createCell(9).setCellValue(supplierQualityPageData.getRows().get(i).getEndTime()); row.createCell(10).setCellValue(supplierQualityPageData.getRows().get(i).getIfStart()); row.createCell(11).setCellValue(supplierQualityPageData.getRows().get(i).getIfEnd()); } } String now = DateUtils.toStr(new Date(), "yyyyMMdd"); String exportFileName = "供应商运营质量报表" + now+".xls"; response.setContentType("application/vnd.ms-excel"); try { response.setHeader("Content-Disposition", "attachment; " + "filename=" + java.net.URLEncoder.encode(exportFileName, "UTF-8")); OutputStream ouputStream = response.getOutputStream(); workBook.write(ouputStream); //exportExcel.write(ouputStream); ouputStream.flush(); ouputStream.close(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
package com.haoxpdp.excelchart; import com.haoxpdp.excelchart.bean.Position; import com.haoxpdp.excelchart.util.DrawUtil; import org.apache.poi.hssf.usermodel.HSSFDataFormat; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; public class Main { public static void main(String[] args) throws IOException { String tmpExcel = "/tmp/tmp.xlsx"; String[] horizontalTitle1 = {"供应商-车型","年月", "订单总数", "自营车辆订单数", "非自营车辆订单数", "自营司机订单数", "非自营司机订单数", "非车辆黑名单订单数", "车辆黑名单订单数", "非司机黑名单订单数", "司机黑名单订单数", "自营车辆比例", "非自营车辆比例", "非自营车辆比例", "非自营司机比例", "非车辆黑名单比例", "车辆黑名单比例", "非司机黑名单比例", "司机黑名单比例"}; String[] horizontalTitle2 = {"供应商-日期-车型", "订单总数", "自营车辆订单数", "非自营车辆订单数", "自营司机订单数", "非自营司机订单数", "非车辆黑名单订单数", "车辆黑名单订单数", "非司机黑名单订单数", "司机黑名单订单数", "自营车辆比例", "非自营车辆比例", "非自营车辆比例", "非自营司机比例", "非车辆黑名单比例", "车辆黑名单比例", "非司机黑名单比例", "司机黑名单比例"}; String[] verticalTitle = {"合易2018-08舒适车-市区", "爱特博2018-08豪华车-跨城"}; String[] horizontalTitleBar1 = {"非自营车辆比例", "非自营司机比例", "车辆黑名单比例", "司机黑名单比例"}; String[] verticalTitle1 = {"合易2018-08舒适车-市区"}; String[] verticalTitle2 = {"爱特博2018-08豪华车-跨城"}; String[] verticalTitle3 = {"非自营车辆订单数", "非自营司机订单数", "车辆黑名单订单数", "司机黑名单订单数"}; Position start1 = new Position(1, 1); Position end1 = new Position(1 + horizontalTitle1.length, 1 + verticalTitle.length); Position start2 = new Position(1, 1); Position end2 = new Position(1 + horizontalTitle2.length, 1 + verticalTitle.length); File file = new File(tmpExcel); createFileDeleteIfExists(file); try ( Workbook wb = new XSSFWorkbook(); OutputStream outputStream = new FileOutputStream(file); ) { XSSFSheet sheet = (XSSFSheet) wb.createSheet(); XSSFSheet sheet1 = (XSSFSheet) wb.createSheet(); XSSFSheet sheet2 = (XSSFSheet) wb.createSheet(); wb.setSheetName(0, "Chart"); wb.setSheetName(1, "Year"); wb.setSheetName(2, "Month"); //隐藏网格线 sheet.setDisplayGridlines(false); Row row = getRow(1, sheet); row.createCell(4).setCellValue("月度分析"); row.createCell(15).setCellValue("年度趋势分析"); writeDataYear(sheet1, horizontalTitle1); writeTitle(horizontalTitle2, sheet2); writeVerticalTitle(verticalTitle, sheet2); writeDataMonth(start2, end2, sheet2); drawMonthBarChart1(sheet, horizontalTitleBar1, verticalTitle1); drawMonthBarChart2(sheet, horizontalTitleBar1, verticalTitle2); drawYearLineChart1(sheet, sheet1); drawYearLineChart2(sheet, sheet1); wb.write(outputStream); } } private static void drawMonthBarChart1(XSSFSheet sheet,String[] horizontalTitle,String[] verticalTitle){ int defaultX = 10; int defaultY = 20; Position chartStart = new Position(0,3); Position chartEnd = new Position(chartStart.getX() + defaultX, chartStart.getY() + defaultY); String[] dataRef = { "Month!$L$2,Month!$N$2,Month!$P$2,Month!$R$2" }; DrawUtil.drawBarChart(sheet,chartStart,chartEnd, Stream.of(horizontalTitle).collect(Collectors.toList()), Stream.of(verticalTitle).collect(Collectors.toSet()), Stream.of(dataRef).collect(Collectors.toList()), verticalTitle[0] ); } private static void drawMonthBarChart2(XSSFSheet sheet,String[] horizontalTitle,String[] verticalTitle){ int defaultX = 10; int defaultY = 20; Position chartStart = new Position(0,defaultY + 4 ); Position chartEnd = new Position(chartStart.getX() + defaultX, chartStart.getY() + defaultY); String[] dataRef = { "Month!$L$3,Month!$N$3,Month!$P$3,Month!$R$3" }; DrawUtil.drawBarChart(sheet,chartStart,chartEnd, Stream.of(horizontalTitle).collect(Collectors.toList()), Stream.of(verticalTitle).collect(Collectors.toSet()), Stream.of(dataRef).collect(Collectors.toList()), verticalTitle[0] ); } private static void drawYearLineChart1(XSSFSheet sheet,XSSFSheet sheet1){ int defaultX = 10; int defaultY = 20; Position chartStart = new Position(11,3); Position chartEnd = new Position(chartStart.getX() + defaultX, chartStart.getY() + defaultY); DrawUtil.drawYearLineChart1(sheet, sheet1, chartStart, chartEnd); } private static void drawYearLineChart2(XSSFSheet sheet,XSSFSheet sheet1){ int defaultX = 10; int defaultY = 20; Position chartStart = new Position(11,defaultY + 4); Position chartEnd = new Position(chartStart.getX() + defaultX, chartStart.getY() + defaultY); DrawUtil.drawYearLineChart2(sheet, sheet1, chartStart, chartEnd); } private static void writeDataYear(XSSFSheet sheet, String[] titleArray) { Row row = getRow(0, sheet); for(int i = 0; i < titleArray.length; i++) { row.createCell(i).setCellValue(titleArray[i]); } for(int i = 0; i < 8; i ++) { Row row2 = getRow(i + 1, sheet); for(int j = 0; j < titleArray.length; j++) { if(j == 1) { row2.createCell(j).setCellValue("2018-0"+(i + 1)); } else { row2.createCell(j).setCellValue(Integer.parseInt(Double.toString(Math.random() * 100).replaceAll("\\.\\d*", ""))); } } } Row row3 = getRow(9, sheet); for(int i = 0; i < titleArray.length; i++) { row3.createCell(i).setCellValue(titleArray[i]); } for(int i = 9; i < 17; i ++) { Row row4 = getRow(i + 1, sheet); for(int j = 0; j < titleArray.length; j++) { if(j == 1) { row4.createCell(j).setCellValue("2018-0" + (i - 8)); } else { row4.createCell(j).setCellValue(Integer.parseInt(Double.toString(Math.random() * 100).replaceAll("\\.\\d*", ""))); } } } } private static void writeDataMonth(Position start, Position end, XSSFSheet xssfSheet) { for (int i = start.getY(); i < end.getY(); i++) { Row row = getRow(i, xssfSheet); for (int j = start.getX(); j < end.getX() - 1; j++) { Cell cell = getCell(j, row); cell.setCellValue(Math.random()); XSSFCellStyle cellStyle = xssfSheet.getWorkbook().createCellStyle(); cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00%")); cell.setCellStyle(cellStyle); } } } private static void writeTitle(String[] title, XSSFSheet sheet) { Row titleRow = getRow(0, sheet); for (int i = 0; i < title.length; i++) { titleRow.createCell(i).setCellValue(title[i]); } } private static void writeVerticalTitle(String[] title, XSSFSheet sheet) { for (int i = 0; i < title.length; i++) { int line = i + 1; Row row = getRow(line, sheet); Cell cell = getCell(0, row); cell.setCellValue(title[i]); } } private static Cell getCell(int index, Row row) { Cell cell = row.getCell(index); if (cell == null) cell = row.createCell(index); return cell; } private static Row getRow(int line, Sheet sheet) { Row row = sheet.getRow(line); if (row == null) row = sheet.createRow(line); return row; } private static void createFileDeleteIfExists(File file) throws IOException { if (file.exists()) { file.delete(); } else { if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); } file.createNewFile(); } }
package com.haoxpdp.excelchart.util; import com.haoxpdp.excelchart.bean.Position; import org.apache.poi.ss.usermodel.Chart; import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.Drawing; import org.apache.poi.ss.usermodel.charts.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFChart; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.openxmlformats.schemas.drawingml.x2006.chart.*; import java.util.Iterator; import java.util.List; import java.util.Set; public class DrawUtil { public static void drawYearLineChart1(XSSFSheet sheet, XSSFSheet sheet1, Position start, Position end) { Drawing drawing = sheet.createDrawingPatriarch(); ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, start.getX(), start.getY(), end.getX(), end.getY()); Chart chart = drawing.createChart(anchor); ChartLegend legend = chart.getOrCreateLegend(); legend.setPosition(LegendPosition.BOTTOM); LineChartData data = chart.getChartDataFactory().createLineChartData(); ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM); ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT); leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); ChartDataSource<String> xs = DataSources.fromStringCellRange(sheet1, new CellRangeAddress(1, 8, 1, 1)); ChartDataSource<Number> ys1 = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(1, 8, 4, 4)); ChartDataSource<Number> ys2 = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(1, 8, 6, 6)); ChartDataSource<Number> ys3 = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(1, 8, 8, 8)); ChartDataSource<Number> ys4 = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(1, 8, 10, 10)); LineChartSeries series1 = data.addSeries(xs, ys1); series1.setTitle("非自营车辆订单数"); LineChartSeries series2 = data.addSeries(xs, ys2); series2.setTitle("非自营司机订单数"); LineChartSeries series3 = data.addSeries(xs, ys3); series3.setTitle("车辆黑名单订单数"); LineChartSeries series4 = data.addSeries(xs, ys4); series4.setTitle("司机黑名单订单数"); setChartTitle((XSSFChart) chart, "合易(舒适车-市区)"); chart.plot(data, bottomAxis, leftAxis); XSSFChart xssfChart = (XSSFChart) chart; CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea(); plotArea.getLineChartArray()[0].getSmooth(); CTBoolean ctBool = CTBoolean.Factory.newInstance(); ctBool.setVal(false); plotArea.getLineChartArray()[0].setSmooth(ctBool); for (CTLineSer ser : plotArea.getLineChartArray()[0].getSerArray()) { ser.setSmooth(ctBool); } } public static void drawYearLineChart2(XSSFSheet sheet, XSSFSheet sheet1, Position start, Position end) { Drawing drawing = sheet.createDrawingPatriarch(); ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, start.getX(), start.getY(), end.getX(), end.getY()); Chart chart = drawing.createChart(anchor); ChartLegend legend = chart.getOrCreateLegend(); legend.setPosition(LegendPosition.BOTTOM); LineChartData data = chart.getChartDataFactory().createLineChartData(); ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM); ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT); leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); ChartDataSource<String> xs = DataSources.fromStringCellRange(sheet1, new CellRangeAddress(10, 17, 1, 1)); ChartDataSource<Number> ys1 = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(10, 17, 4, 4)); ChartDataSource<Number> ys2 = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(10, 17, 6, 6)); ChartDataSource<Number> ys3 = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(10, 17, 8, 8)); ChartDataSource<Number> ys4 = DataSources.fromNumericCellRange(sheet1, new CellRangeAddress(10, 17, 10, 10)); LineChartSeries series1 = data.addSeries(xs, ys1); series1.setTitle("非自营车辆订单数"); LineChartSeries series2 = data.addSeries(xs, ys2); series2.setTitle("非自营司机订单数"); LineChartSeries series3 = data.addSeries(xs, ys3); series3.setTitle("车辆黑名单订单数"); LineChartSeries series4 = data.addSeries(xs, ys4); series4.setTitle("司机黑名单订单数"); setChartTitle((XSSFChart) chart, "爱特博(豪华车-跨城)"); chart.plot(data, bottomAxis, leftAxis); XSSFChart xssfChart = (XSSFChart) chart; CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea(); plotArea.getLineChartArray()[0].getSmooth(); CTBoolean ctBool = CTBoolean.Factory.newInstance(); ctBool.setVal(false); plotArea.getLineChartArray()[0].setSmooth(ctBool); for (CTLineSer ser : plotArea.getLineChartArray()[0].getSerArray()) { ser.setSmooth(ctBool); } } /* * @param position 图表坐标 起始行,起始列,终点行,重点列 * * @param xString 横坐标 * * @param serTxName 图形示例 * * @param dataRef 柱状图数据范围 : sheetName!$A$1:$A$12 */ public static void drawBarChart(XSSFSheet sheet, Position start, Position end, List<String> xString, Set<String> serTxName, List<String> dataRef, String chartTitle) { Drawing drawing = sheet.createDrawingPatriarch(); ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, start.getX(), start.getY(), end.getX(), end.getY()); Chart chart = drawing.createChart(anchor); CTChart ctChart = ((XSSFChart) chart).getCTChart(); CTPlotArea ctPlotArea = ctChart.getPlotArea(); CTBarChart ctBarChart = ctPlotArea.addNewBarChart(); ctBarChart.addNewVaryColors().setVal(false); ctBarChart.addNewBarDir().setVal(STBarDir.COL); // telling the Chart that it has axis and giving them Ids setAxIds(ctBarChart); // set cat axis setCatAx(ctPlotArea); // set val axis setValAx(ctPlotArea); // add legend and set legend position setLegend(ctChart); // set data lable setDataLabel(ctBarChart); // set chart title setChartTitle((XSSFChart) chart, chartTitle); // padding data to chart paddingData(ctBarChart, xString, serTxName, dataRef); } private static void paddingData(CTBarChart ctBarChart, List<String> xString, Set<String> serTxName, List<String> dataRef) { Iterator<String> iterator = serTxName.iterator(); for (int r = 0, len = dataRef.size(); r < len && iterator.hasNext(); r++) { CTBarSer ctBarSer = ctBarChart.addNewSer(); ctBarSer.addNewIdx().setVal(r); // set legend value setLegend(iterator.next(), ctBarSer.addNewTx()); // cat ax value setChartCatAxLabel(ctBarSer.addNewCat(), xString); // value range ctBarSer.addNewVal().addNewNumRef().setF(dataRef.get(r)); // add border to chart ctBarSer.addNewSpPr().addNewLn().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{0, 0, 0}); } } private static void setLegend(String str, CTSerTx ctSerTx) { if (str.contains("$")) // set legend by str ref ctSerTx.addNewStrRef().setF(str); else // set legend by str ctSerTx.setV(str); } private static void setChartCatAxLabel(CTAxDataSource cttAxDataSource, List<String> xString) { if (xString.size() == 1) { cttAxDataSource.addNewStrRef().setF(xString.get(0)); } else { CTStrData ctStrData = cttAxDataSource.addNewStrLit(); for (int m = 0, xlen = xString.size(); m < xlen; m++) { CTStrVal ctStrVal = ctStrData.addNewPt(); ctStrVal.setIdx((long) m); ctStrVal.setV(xString.get(m)); } } } private static void setDataLabel(CTBarChart ctBarChart) { setDLShowOpts(ctBarChart.addNewDLbls()); } private static void setDataLabel(CTLineChart ctLineChart) { CTDLbls dlbls = ctLineChart.addNewDLbls(); setDLShowOpts(dlbls); setDLPosition(dlbls, null); } private static void setDLPosition(CTDLbls dlbls, STDLblPos.Enum e) { if (e == null) dlbls.addNewDLblPos().setVal(STDLblPos.T); else dlbls.addNewDLblPos().setVal(e); } private static void setDLShowOpts(CTDLbls dlbls) { // 添加图形示例的字符串 dlbls.addNewShowSerName().setVal(false); // 添加x轴的坐标字符串 dlbls.addNewShowCatName().setVal(false); // 添加图形示例的图片 dlbls.addNewShowLegendKey().setVal(false); // 添加x对应y的值---全设置成false 就没什么用处了 // dlbls.addNewShowVal().setVal(false); } private static void setAxIds(CTBarChart ctBarChart) { ctBarChart.addNewAxId().setVal(123456); ctBarChart.addNewAxId().setVal(123457); } private static void setAxIds(CTLineChart ctLineChart) { ctLineChart.addNewAxId().setVal(123456); ctLineChart.addNewAxId().setVal(123457); } private static void setLegend(CTChart ctChart) { CTLegend ctLegend = ctChart.addNewLegend(); ctLegend.addNewLegendPos().setVal(STLegendPos.B); ctLegend.addNewOverlay().setVal(false); } private static void setCatAx(CTPlotArea ctPlotArea) { CTCatAx ctCatAx = ctPlotArea.addNewCatAx(); ctCatAx.addNewAxId().setVal(123456); // id of the cat axis CTScaling ctScaling = ctCatAx.addNewScaling(); ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX); ctCatAx.addNewDelete().setVal(false); ctCatAx.addNewAxPos().setVal(STAxPos.B); ctCatAx.addNewCrossAx().setVal(123457); // id of the val axis ctCatAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO); } // 不要y轴的标签,或者y轴尽可能的窄一些 private static void setValAx(CTPlotArea ctPlotArea) { CTValAx ctValAx = ctPlotArea.addNewValAx(); ctValAx.addNewAxId().setVal(123457); // id of the val axis CTScaling ctScaling = ctValAx.addNewScaling(); ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX); // 不现实y轴ki ctValAx.addNewDelete().setVal(true); ctValAx.addNewAxPos().setVal(STAxPos.L); ctValAx.addNewCrossAx().setVal(123456); // id of the cat axis ctValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO); } // 图标标题 private static void setChartTitle(XSSFChart xchart, String titleStr) { CTChart ctChart = xchart.getCTChart(); CTTitle title = CTTitle.Factory.newInstance(); CTTx cttx = title.addNewTx(); CTStrData sd = CTStrData.Factory.newInstance(); CTStrVal str = sd.addNewPt(); str.setIdx(123459); str.setV(titleStr); cttx.addNewStrRef().setStrCache(sd); ctChart.setTitle(title); } }
package com.haoxpdp.excelchart.bean; public class Position { int x; int y; public Position(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public Position setX(int x) { this.x = x; return this; } public int getY() { return y; } public Position setY(int y) { this.y = y; return this; } @Override public String toString() { return "Position{" + "x=" + x + ", y=" + y + '}'; } }