건설현장 관리>건설현장 조회: 엑셀다운로드 처리시 progress 표시
parent
804309bbd5
commit
715687e8d2
|
|
@ -44,7 +44,6 @@ import geoinfo.com.EgovExcel;
|
||||||
import geoinfo.comm.util.ScriptUtil;
|
import geoinfo.comm.util.ScriptUtil;
|
||||||
import geoinfo.comm.util.strUtil;
|
import geoinfo.comm.util.strUtil;
|
||||||
import geoinfo.session.UserInfo;
|
import geoinfo.session.UserInfo;
|
||||||
import geoinfo.util.ExcelJobManager;
|
|
||||||
import geoinfo.util.ExcelMergeHeaderUtil;
|
import geoinfo.util.ExcelMergeHeaderUtil;
|
||||||
import geoinfo.util.MyUtil;
|
import geoinfo.util.MyUtil;
|
||||||
|
|
||||||
|
|
@ -887,42 +886,75 @@ public class ConstructionProjectManagementController {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 발주기관 건설현장 CSV 다운로드 처리
|
* 발주기관 건설현장 엑셀 다운로드 처리(진행률 표시)
|
||||||
* @param workbook
|
* @param workbook
|
||||||
* @param request
|
* @param request
|
||||||
* @param response
|
* @param response
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.POST, value="/admins/drilling/inquiry/excel/start.do")
|
@RequestMapping(value = "admins/drilling/inquiry/excel.do")
|
||||||
@ResponseBody
|
public void downloadDrillingInquiryListExcel(HttpServletRequest request, HttpServletResponse response, @RequestParam HashMap<String, Object> params) throws Exception {
|
||||||
public Map<String,Object> downloadDrillingInquiryListExcel(HttpServletRequest request, @RequestParam HashMap<String, Object> params) throws Exception {
|
|
||||||
|
|
||||||
final String jobId = UUID.randomUUID().toString();
|
// =========================
|
||||||
final HttpServletRequest finalRequest = request;
|
// 1. 엑셀 헤더 정보 구성
|
||||||
final HashMap<String,Object> finalParams = params;
|
// =========================
|
||||||
final DrillingInquiryService service = drillingInquiryService;
|
String[] headers = {
|
||||||
String excelFileName = "발주기관_건설현장_목록_" + ExcelMergeHeaderUtil.getTimeStampString("yyyyMMdd_HHmm") + ".xlsx";
|
"cid","constName","projectStateCodeName","constStartDate",
|
||||||
|
"constStateCodeName","inquiryDist","masterCompanyDept",
|
||||||
|
"masterCompanyAdmin","masterCompanyTel","coinstCompanyDept",
|
||||||
|
"constCompanyAdmin","constCompanyTel"
|
||||||
|
};
|
||||||
|
|
||||||
ExcelJobManager.startJob(jobId, new ExcelJobManager.ExcelTask() {
|
String[][] headerNames = {
|
||||||
public byte[] generate(ExcelJobManager.ProgressCallback callback) throws Exception {
|
{"연번", "사업명", "입력상태", "사업내용", "", "발주기관현황", "", "", "", "건설사현황", "", ""},
|
||||||
|
{"", "", "", "사업기간", "사업단계", "발주처", "담당부서",
|
||||||
|
"담당자", "담당자연락처", "건설사명", "담당자", "담당자연락처"}
|
||||||
|
};
|
||||||
|
|
||||||
String[] headers = {"cid","constName","projectStateCodeName","constStartDate","constStateCodeName","inquiryDist" ,"masterCompanyDept","masterCompanyAdmin","masterCompanyTel","coinstCompanyDept","constCompanyAdmin","constCompanyTel"};
|
final int[] headerWidths = {
|
||||||
String[][] headerNames = {{"연번", "사업명", "입력상태", "사업내용", "", "발주기관현황", "", "", "", "건설사현황", "", ""},
|
1325,15900,4240,6360,5830,8830,
|
||||||
{"", "", "", "사업기간", "사업단계", "발주처", "담당부서", "담당자", "담당자연락처", "건설사명", "담당자", "담당자연락처"}};
|
6890,2915,3710,5035,2915,3710
|
||||||
|
};
|
||||||
|
|
||||||
|
String[] columnType = {
|
||||||
|
"String","String","String","String","String","String",
|
||||||
|
"String","String","String","String","String","String"
|
||||||
|
};
|
||||||
|
|
||||||
final int[] headerWidths = {1325, 15900, 4240, 6360, 5830, 8830, 6890, 2915, 3710, 5035, 2915, 3710};
|
|
||||||
String[] columnType = {"String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String"};
|
|
||||||
String sheetName = "Sheet1";
|
String sheetName = "Sheet1";
|
||||||
|
String excelFileName = "발주기관 건설현장 목록";
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 2. DB 조회
|
||||||
|
// =========================
|
||||||
|
JSONObject resultObj = drillingInquiryService.drillingInquiryList(request, params);
|
||||||
|
|
||||||
JSONObject resultObj = drillingInquiryService.drillingInquiryList(finalRequest, finalParams);
|
|
||||||
List<EgovMap> list = (List<EgovMap>) resultObj.get("datas");
|
List<EgovMap> list = (List<EgovMap>) resultObj.get("datas");
|
||||||
Long totalCount = (Long) resultObj.get("count");
|
Long totalCount = (Long) resultObj.get("count");
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 3. 데이터 없으면 리턴
|
||||||
|
// =========================
|
||||||
|
if (list == null || list.isEmpty()) {
|
||||||
|
response.setContentType("text/html;charset=UTF-8");
|
||||||
|
response.getWriter().write("<script>alert('데이터가 없습니다.');</script>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 4. 리스트 후처리
|
||||||
|
// =========================
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (EgovMap rowData : list) {
|
for (EgovMap rowData : list) {
|
||||||
|
|
||||||
String constStartDate = (String) rowData.get("constStartDate");
|
String constStartDate = (String) rowData.get("constStartDate");
|
||||||
String constEndDate = (String) rowData.get("constEndDate");
|
String constEndDate = (String) rowData.get("constEndDate");
|
||||||
rowData.put("constStartDate", constStartDate + " ~ " + constEndDate);
|
|
||||||
|
rowData.put("constStartDate",
|
||||||
|
(constStartDate == null ? "" : constStartDate)
|
||||||
|
+ " ~ "
|
||||||
|
+ (constEndDate == null ? "" : constEndDate));
|
||||||
|
|
||||||
rowData.put("cid", (totalCount) - (idx++));
|
rowData.put("cid", (totalCount) - (idx++));
|
||||||
|
|
||||||
String inquiryDist = "";
|
String inquiryDist = "";
|
||||||
|
|
@ -933,19 +965,22 @@ public class ConstructionProjectManagementController {
|
||||||
if (rowData.get("gsName") != null)
|
if (rowData.get("gsName") != null)
|
||||||
inquiryDist += rowData.get("gsName");
|
inquiryDist += rowData.get("gsName");
|
||||||
|
|
||||||
rowData.put("inquiryDist", inquiryDist);
|
rowData.put("inquiryDist", inquiryDist.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] excelBytes = ExcelMergeHeaderUtil.listToExcelMergeHeaderByteArray(list, headers, headerNames, headerWidths, columnType, "Sheet1", callback);
|
// =========================
|
||||||
|
// 5. 엑셀 유틸 호출
|
||||||
return excelBytes;
|
// =========================
|
||||||
|
ExcelMergeHeaderUtil.listToExcelMergeHeader(
|
||||||
}
|
list,
|
||||||
}, excelFileName);
|
response,
|
||||||
|
headers,
|
||||||
Map<String,Object> result = new HashMap<String,Object>();
|
headerNames,
|
||||||
result.put("jobId", jobId);
|
headerWidths,
|
||||||
return result;
|
columnType,
|
||||||
|
sheetName,
|
||||||
|
excelFileName
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1119,45 +1154,4 @@ public class ConstructionProjectManagementController {
|
||||||
ExcelMergeHeaderUtil.listToExcelMergeHeaderForLoginHistory(resultList, response, headers, headerNames, headerWidths, columnType, sheetName, excelFileName);
|
ExcelMergeHeaderUtil.listToExcelMergeHeaderForLoginHistory(resultList, response, headers, headerNames, headerWidths, columnType, sheetName, excelFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 엑셀 다운로드 로딩 표시(진행률 확인)
|
|
||||||
* @param jobId
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@RequestMapping(value="/admins/drilling/inquiry/excel/progress.do", method=RequestMethod.GET)
|
|
||||||
@ResponseBody
|
|
||||||
public Map<String,Object> getExcelProgress(@RequestParam String jobId) {
|
|
||||||
int progress = ExcelJobManager.getProgress(jobId);
|
|
||||||
Map<String,Object> result = new HashMap<>();
|
|
||||||
result.put("progress", progress);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 엑셀 다운로드 로딩 표시(다운로드 완료)
|
|
||||||
* @param jobId
|
|
||||||
* @param response
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@RequestMapping(value="/admins/drilling/inquiry/excel/download.do", method=RequestMethod.GET)
|
|
||||||
public void downloadExcel(@RequestParam String jobId, HttpServletResponse response) throws IOException {
|
|
||||||
byte[] data = ExcelJobManager.getResult(jobId);
|
|
||||||
if(data == null){
|
|
||||||
response.sendError(404, "엑셀 파일을 찾을 수 없습니다.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Job 단위로 저장된 파일명 사용
|
|
||||||
String fileName = ExcelJobManager.getFileName(jobId);
|
|
||||||
fileName = java.net.URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
|
|
||||||
|
|
||||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
|
|
||||||
response.setHeader("Content-Transfer-Encoding", "binary");
|
|
||||||
response.setContentType("application/octet-stream");
|
|
||||||
response.getOutputStream().write(data);
|
|
||||||
response.flushBuffer();
|
|
||||||
|
|
||||||
// 완료 후 캐시 제거
|
|
||||||
ExcelJobManager.clear(jobId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
package geoinfo.util;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import org.json.simple.JSONObject;
|
|
||||||
|
|
||||||
import egovframework.rte.psl.dataaccess.util.EgovMap;
|
|
||||||
import geoinfo.admins.user.service.DrillingInquiryService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 엑셀 다운로드 로딩바 처리 유틸
|
|
||||||
* @author JIYOO
|
|
||||||
*/
|
|
||||||
public class ExcelJobManager {
|
|
||||||
|
|
||||||
private static class Job {
|
|
||||||
byte[] data;
|
|
||||||
String fileName;
|
|
||||||
int progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Map<String, Job> jobMap = new ConcurrentHashMap<String, Job>();
|
|
||||||
|
|
||||||
public static void startJob(final String jobId, final ExcelTask excelTask, final String fileName) {
|
|
||||||
final Job job = new Job();
|
|
||||||
job.progress = 0;
|
|
||||||
job.fileName = fileName;
|
|
||||||
jobMap.put(jobId, job);
|
|
||||||
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
byte[] excelBytes = excelTask.generate(new ProgressCallback() {
|
|
||||||
@Override
|
|
||||||
public void update(int percent) {
|
|
||||||
job.progress = percent;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
job.data = excelBytes;
|
|
||||||
job.progress = 100;
|
|
||||||
} catch (Exception e) {
|
|
||||||
job.progress = -1;
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getProgress(String jobId) {
|
|
||||||
Job job = jobMap.get(jobId);
|
|
||||||
return job == null ? 0 : job.progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] getResult(String jobId) {
|
|
||||||
Job job = jobMap.get(jobId);
|
|
||||||
return job == null ? null : job.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFileName(String jobId) {
|
|
||||||
Job job = jobMap.get(jobId);
|
|
||||||
return job == null ? "excel.xlsx" : job.fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void clear(String jobId) {
|
|
||||||
jobMap.remove(jobId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface ProgressCallback {
|
|
||||||
void update(int percent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface ExcelTask {
|
|
||||||
byte[] generate(ProgressCallback callback) throws Exception;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,6 +2,7 @@ package geoinfo.util;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
@ -17,6 +18,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
import org.apache.poi.ss.usermodel.CellStyle;
|
import org.apache.poi.ss.usermodel.CellStyle;
|
||||||
|
import org.apache.poi.ss.usermodel.DataFormat;
|
||||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||||
import org.apache.poi.ss.usermodel.Font;
|
import org.apache.poi.ss.usermodel.Font;
|
||||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||||
|
|
@ -24,7 +26,9 @@ import org.apache.poi.ss.usermodel.IndexedColors;
|
||||||
import org.apache.poi.ss.usermodel.Row;
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
||||||
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
import org.apache.poi.ss.util.CellRangeAddress;
|
import org.apache.poi.ss.util.CellRangeAddress;
|
||||||
|
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFDataFormat;
|
import org.apache.poi.xssf.usermodel.XSSFDataFormat;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
|
||||||
|
|
@ -233,7 +237,8 @@ public class ExcelMergeHeaderUtil {
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (ExcelMergeHeaderUtil.isNotEmpty(list)) {
|
if (ExcelMergeHeaderUtil.isNotEmpty(list)) {
|
||||||
// 메모리에 100개의 행을 유지합니다. 행의 수가 넘으면 디스크에 적습니다.
|
// 메모리에 100개의 행을 유지합니다. 행의 수가 넘으면 디스크에 적습니다.
|
||||||
XSSFWorkbook wb = new XSSFWorkbook();
|
// XSSFWorkbook wb = new XSSFWorkbook();
|
||||||
|
Workbook wb = new SXSSFWorkbook(200);
|
||||||
Sheet sheet = wb.createSheet(sheetName);
|
Sheet sheet = wb.createSheet(sheetName);
|
||||||
Row headerRow = sheet.createRow(headerNames.length);
|
Row headerRow = sheet.createRow(headerNames.length);
|
||||||
CellStyle cellStyle1 = wb.createCellStyle(); // 쉼표들어간 숫자 양식
|
CellStyle cellStyle1 = wb.createCellStyle(); // 쉼표들어간 숫자 양식
|
||||||
|
|
@ -252,7 +257,8 @@ public class ExcelMergeHeaderUtil {
|
||||||
headerFont.setColor(IndexedColors.WHITE.getIndex()); // 글씨 색상 흰색
|
headerFont.setColor(IndexedColors.WHITE.getIndex()); // 글씨 색상 흰색
|
||||||
headerStyle.setFont(headerFont); // 헤더 스타일에 적용
|
headerStyle.setFont(headerFont); // 헤더 스타일에 적용
|
||||||
|
|
||||||
XSSFDataFormat format = wb.createDataFormat();
|
// XSSFDataFormat format = wb.createDataFormat();
|
||||||
|
DataFormat format = wb.createDataFormat();
|
||||||
cellStyle1.setDataFormat(format.getFormat("#,##0"));
|
cellStyle1.setDataFormat(format.getFormat("#,##0"));
|
||||||
cellStyle2.setDataFormat(format.getFormat("#"));
|
cellStyle2.setDataFormat(format.getFormat("#"));
|
||||||
headerStyle.setBorderTop(BorderStyle.THIN);
|
headerStyle.setBorderTop(BorderStyle.THIN);
|
||||||
|
|
@ -345,13 +351,34 @@ public class ExcelMergeHeaderUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 엑셀이름 한글깨짐방지
|
// 엑셀이름 한글깨짐방지
|
||||||
String outputFileName = new String(excelFileName.getBytes("KSC5601"), "8859_1");
|
String encodedFileName = URLEncoder.encode(excelFileName, "UTF-8").replaceAll("\\+", "%20");
|
||||||
|
|
||||||
response.setHeader("Set-Cookie", "fileDownload=true; path=/");
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
response.setHeader("Content-Disposition", String.format("attachment; filename=\"" + outputFileName + "_"
|
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName + "_"
|
||||||
+ ExcelMergeHeaderUtil.getTimeStampString("yyyyMMdd_HHmm") + ".xlsx\""));
|
+ ExcelMergeHeaderUtil.getTimeStampString("yyyyMMdd_HHmm") + ".xlsx");
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 엑셀을 ByteArray로 생성
|
||||||
|
// =========================
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
wb.write(bos);
|
||||||
|
|
||||||
|
if (wb instanceof SXSSFWorkbook) {
|
||||||
|
((SXSSFWorkbook) wb).dispose(); // temp 파일 정리
|
||||||
|
}
|
||||||
|
wb.close();
|
||||||
|
|
||||||
|
byte[] fileBytes = bos.toByteArray();
|
||||||
|
response.setContentLength(fileBytes.length);
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 전송
|
||||||
|
// =========================
|
||||||
|
OutputStream os = response.getOutputStream();
|
||||||
|
os.write(fileBytes);
|
||||||
|
os.flush();
|
||||||
|
os.close();
|
||||||
|
|
||||||
wb.write(response.getOutputStream());
|
|
||||||
wb.close();
|
wb.close();
|
||||||
} else {
|
} else {
|
||||||
createNoDataAlert(response);
|
createNoDataAlert(response);
|
||||||
|
|
@ -359,104 +386,6 @@ public class ExcelMergeHeaderUtil {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 로딩바 표시를 위하여 응답을 return함
|
|
||||||
*
|
|
||||||
* @param response
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
// public static byte[] listToExcelMergeHeaderByteArray(List<EgovMap> list,
|
|
||||||
// String[] headers, String[][] headerNames, int[] headerWidths, String[]
|
|
||||||
// columnType, String sheetName) throws IOException {
|
|
||||||
public static byte[] listToExcelMergeHeaderByteArray(List<EgovMap> list, String[] headers, String[][] headerNames,
|
|
||||||
int[] headerWidths, String[] columnType, String sheetName, ExcelJobManager.ProgressCallback callback)
|
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
if (!ExcelMergeHeaderUtil.isNotEmpty(list)) {
|
|
||||||
return new byte[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
XSSFWorkbook wb = new XSSFWorkbook();
|
|
||||||
Sheet sheet = wb.createSheet(sheetName);
|
|
||||||
|
|
||||||
CellStyle headerStyle = wb.createCellStyle();
|
|
||||||
CellStyle borderStyle = wb.createCellStyle();
|
|
||||||
CellStyle cellStyle1 = wb.createCellStyle();
|
|
||||||
CellStyle cellStyle2 = wb.createCellStyle();
|
|
||||||
|
|
||||||
// ===== 스타일 설정 =====
|
|
||||||
borderStyle.setBorderTop(BorderStyle.THIN);
|
|
||||||
borderStyle.setBorderBottom(BorderStyle.THIN);
|
|
||||||
borderStyle.setBorderLeft(BorderStyle.THIN);
|
|
||||||
borderStyle.setBorderRight(BorderStyle.THIN);
|
|
||||||
|
|
||||||
Font headerFont = wb.createFont();
|
|
||||||
headerFont.setColor(IndexedColors.WHITE.getIndex());
|
|
||||||
headerStyle.setFont(headerFont);
|
|
||||||
headerStyle.cloneStyleFrom(borderStyle);
|
|
||||||
headerStyle.setAlignment(HorizontalAlignment.CENTER);
|
|
||||||
headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
|
||||||
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
|
||||||
headerStyle.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.getIndex());
|
|
||||||
|
|
||||||
XSSFDataFormat format = wb.createDataFormat();
|
|
||||||
cellStyle1.setDataFormat(format.getFormat("#,##0"));
|
|
||||||
cellStyle2.setDataFormat(format.getFormat("#"));
|
|
||||||
|
|
||||||
// ===== 헤더 병합 =====
|
|
||||||
sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 0));
|
|
||||||
sheet.addMergedRegion(new CellRangeAddress(0, 1, 1, 1));
|
|
||||||
sheet.addMergedRegion(new CellRangeAddress(0, 1, 2, 2));
|
|
||||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 3, 4));
|
|
||||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 5, 8));
|
|
||||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 9, 11));
|
|
||||||
|
|
||||||
// ===== 헤더 생성 =====
|
|
||||||
for (int i = 0; i < headerNames.length; i++) {
|
|
||||||
Row row = sheet.createRow(i);
|
|
||||||
for (int j = 0; j < headerNames[i].length; j++) {
|
|
||||||
Cell cell = row.createCell(j);
|
|
||||||
cell.setCellValue(headerNames[i][j]);
|
|
||||||
cell.setCellStyle(headerStyle);
|
|
||||||
sheet.setColumnWidth(j, headerWidths[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 바디 =====
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
|
||||||
EgovMap rowData = list.get(i);
|
|
||||||
Row row = sheet.createRow(i + 2);
|
|
||||||
|
|
||||||
for (int j = 0; j < headers.length; j++) {
|
|
||||||
Cell cell = row.createCell(j);
|
|
||||||
Object value = rowData.get(headers[j]);
|
|
||||||
|
|
||||||
if ("Money".equalsIgnoreCase(columnType[j])) {
|
|
||||||
cell.setCellValue(value instanceof Number ? ((Number) value).doubleValue() : 0);
|
|
||||||
cell.setCellStyle(cellStyle1);
|
|
||||||
} else if ("Int".equalsIgnoreCase(columnType[j])) {
|
|
||||||
cell.setCellValue(value instanceof Number ? ((Number) value).doubleValue() : 0);
|
|
||||||
cell.setCellStyle(cellStyle2);
|
|
||||||
} else {
|
|
||||||
cell.setCellValue(value == null ? "" : String.valueOf(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
cell.setCellStyle(borderStyle);
|
|
||||||
// 진행률 계산 (중간중간 콜백 호출)
|
|
||||||
if (callback != null) {
|
|
||||||
int percent = (int) (((i + 1) / (double) list.size()) * 100);
|
|
||||||
callback.update(percent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
wb.write(bos);
|
|
||||||
wb.close();
|
|
||||||
|
|
||||||
return bos.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void createNoDataAlert(HttpServletResponse response) throws IOException {
|
private static void createNoDataAlert(HttpServletResponse response) throws IOException {
|
||||||
response.setHeader("Content-Type", "text/html; charset=UTF-8");
|
response.setHeader("Content-Type", "text/html; charset=UTF-8");
|
||||||
PrintWriter out = response.getWriter();
|
PrintWriter out = response.getWriter();
|
||||||
|
|
|
||||||
|
|
@ -698,6 +698,101 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
$(document).on("click", '#btnSubmit', function(e) {
|
||||||
|
|
||||||
|
var canvasModal = parent.document.getElementById("canvasModal");
|
||||||
|
var canvas = parent.document.getElementById("canvas");
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
function showPer(per) {
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
// 원형 진행률
|
||||||
|
ctx.strokeStyle = "#f66";
|
||||||
|
ctx.lineWidth = 10;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(canvas.width/2, canvas.height/2, 50, -Math.PI/2, (-Math.PI/2 + 2*Math.PI*per/100));
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
// 숫자 표시
|
||||||
|
ctx.font = '20px Arial';
|
||||||
|
ctx.fillStyle = "#fff";
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.textBaseline = 'middle';
|
||||||
|
ctx.fillText(per + '%', canvas.width/2, canvas.height/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.append("constTag", trim($('#const-tag').val()));
|
||||||
|
params.append("constName", trim($('#const-name').val()));
|
||||||
|
params.append("excelDownload", "Y");
|
||||||
|
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "/admins/drilling/inquiry/excel.do?" + params.toString(), true);
|
||||||
|
xhr.responseType = "blob";
|
||||||
|
|
||||||
|
var fakePer = 0;
|
||||||
|
var fakeInterval;
|
||||||
|
|
||||||
|
xhr.onloadstart = function () {
|
||||||
|
canvasModal.style.display = "flex"; // 모달 표시
|
||||||
|
fakePer = 0;
|
||||||
|
showPer(4);
|
||||||
|
|
||||||
|
// fake progress 시작 (0~90%)
|
||||||
|
fakeInterval = setInterval(function() {
|
||||||
|
if (fakePer < 90) {
|
||||||
|
fakePer += Math.random() * 3; // 0~3%씩 증가
|
||||||
|
showPer(Math.floor(fakePer));
|
||||||
|
}
|
||||||
|
}, 100); // 0.1초마다 증가
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onprogress = function (e) {
|
||||||
|
if (e.lengthComputable) {
|
||||||
|
showPer(Math.floor((e.loaded / e.total) * 100));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onload = function () {
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
var blob = xhr.response;
|
||||||
|
|
||||||
|
// 서버에서 보낸 Content-Disposition 헤더 확인
|
||||||
|
var disposition = xhr.getResponseHeader('Content-Disposition');
|
||||||
|
var fileName = "excel.xlsx"; // 기본 파일명
|
||||||
|
if (disposition && disposition.indexOf('filename*=') !== -1) {
|
||||||
|
var matches = disposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
|
||||||
|
if (matches != null && matches[1]) {
|
||||||
|
fileName = decodeURIComponent(matches[1]);
|
||||||
|
// 접두사 UTF-8'' 제거
|
||||||
|
fileName = fileName.replace(/^UTF-8''/, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blob 다운로드
|
||||||
|
var link = document.createElement("a");
|
||||||
|
link.href = window.URL.createObjectURL(blob);
|
||||||
|
link.download = fileName; // 서버에서 가져온 이름 사용
|
||||||
|
document.body.appendChild(link); // Firefox에서 필요
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onloadend = function () {
|
||||||
|
clearInterval(fakeInterval); // fake progress 중지
|
||||||
|
showPer(100);
|
||||||
|
setTimeout(function () {
|
||||||
|
canvasModal.style.display = "none"; // 모달 숨김
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
});
|
||||||
</script><style>
|
</script><style>
|
||||||
.drilling .page-content-inner {
|
.drilling .page-content-inner {
|
||||||
padding: 30px 0;
|
padding: 30px 0;
|
||||||
|
|
@ -882,8 +977,7 @@ li {
|
||||||
</div>
|
</div>
|
||||||
<div class="table-info-group">
|
<div class="table-info-group">
|
||||||
<span>Total: <span id="count">-</span>건</span>
|
<span>Total: <span id="count">-</span>건</span>
|
||||||
<%-- <span class="pull-right"><img src="${pageContext.request.contextPath}/images/admins/excel.gif" style="cursor:hand" onClick="javascript:clickExcelDownload()"></span> --%>
|
<span class="pull-right" id="btnSubmit"><img src="${pageContext.request.contextPath}/images/admins/excel.gif" style="cursor:hand"</span>
|
||||||
<span class="pull-right"><img src="${pageContext.request.contextPath}/images/admins/excel.gif" style="cursor:hand" onClick="startExcelDownload()"></span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="table-wrap">
|
<div class="table-wrap">
|
||||||
<table>
|
<table>
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,19 @@ function hideLoadingBar() {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#canvasModal {
|
||||||
|
display:none;
|
||||||
|
position:fixed;
|
||||||
|
top:0;
|
||||||
|
left:0;
|
||||||
|
width:100%;
|
||||||
|
height:100%;
|
||||||
|
background: rgba(0,0,0,0.5);
|
||||||
|
z-index:9999;
|
||||||
|
align-items:center;
|
||||||
|
justify-content:center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body leftmargin="0" topmargin="0" marginheight="0" marginwidth="0">
|
<body leftmargin="0" topmargin="0" marginheight="0" marginwidth="0">
|
||||||
|
|
@ -101,5 +114,9 @@ function hideLoadingBar() {
|
||||||
<div id="progressText">0%</div>
|
<div id="progressText">0%</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Canvas Modal -->
|
||||||
|
<div id="canvasModal">
|
||||||
|
<canvas id="canvas" width="120" height="120" style="background:none;"></canvas>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue