From 46cc5a5b5bb7791d862e30c3a63e506404ccc7ed Mon Sep 17 00:00:00 2001 From: keke Date: Thu, 31 Aug 2023 13:45:44 +0800 Subject: [PATCH] =?UTF-8?q?[FE=20API]=20=E5=AE=8C=E6=88=90=20=E5=90=84?= =?UTF-8?q?=E5=88=86=E7=9B=A4=E7=B8=BD=E8=A1=A8=E6=AF=94=E8=BC=83=E5=A0=B1?= =?UTF-8?q?=E8=A1=A8=E5=8C=AF=E5=87=BA=E5=8A=9F=E8=83=BD=20=E5=B0=8F?= =?UTF-8?q?=E6=95=B8=E9=BB=9E=E5=85=A8=E9=83=A8=E5=9B=9B=E6=8D=A8=E4=BA=94?= =?UTF-8?q?=E5=85=A5=E5=88=B0=E7=82=BA=E6=95=B4=E6=95=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ApiControllers/HydroMeterController.cs | 309 +++++++++++++----- .../ElectricEachTotalCompare_temp.xlsx | Bin 13749 -> 13074 bytes 2 files changed, 236 insertions(+), 73 deletions(-) diff --git a/FrontendWebApi/ApiControllers/HydroMeterController.cs b/FrontendWebApi/ApiControllers/HydroMeterController.cs index 7038ff7..08985a7 100644 --- a/FrontendWebApi/ApiControllers/HydroMeterController.cs +++ b/FrontendWebApi/ApiControllers/HydroMeterController.cs @@ -18,6 +18,9 @@ using System.Text; using iTextSharp.text; using System.Collections; using Google.Protobuf.Collections; +using Org.BouncyCastle.Asn1.Pkcs; +using NPOI.SS.Formula.Functions; +using static ICSharpCode.SharpZipLib.Zip.ExtendedUnixData; namespace FrontendWebApi.ApiControllers { @@ -25,6 +28,7 @@ namespace FrontendWebApi.ApiControllers { private readonly IBackendRepository backendRepository; private readonly IFrontendRepository frontendRepository; + private ICellStyle greencellstyle; public HydroMeterController(IBackendRepository backendRepository, IFrontendRepository frontendRepository) { @@ -830,57 +834,82 @@ namespace FrontendWebApi.ApiControllers public FileResult OpeExportEachTotalCompareExcelElec([FromBody] HydroMeterInput input) { List result = new List(); - + List result_for_sum = new List(); result = ElectricListEachTotal(input).Result.Value.Data.ToList(); + bool flag = true; + bool total_flag = false; + if (input.Mode == HydroMeterInputSearchMode.Custom) + { + result_for_sum = ElectricListEachTotal(input).Result.Value.Data.ToList(); + flag = false; + total_flag = true; + } + else + { + result_for_sum = new List(result); + } + List> docFile = new List>(); - var workbook = new XSSFWorkbook(); - #region excel設定 - IFont font12 = workbook.CreateFont(); - font12.FontName = "新細明體"; - font12.FontHeightInPoints = 12; - ICellStyle style12 = workbook.CreateCellStyle(); - style12.SetFont(font12); - style12.Alignment = HorizontalAlignment.Center; - style12.VerticalAlignment = VerticalAlignment.Center; - IFont font12Times = workbook.CreateFont(); - font12Times.FontName = "Times New Roman"; - font12Times.FontHeightInPoints = 12; - IFont font18 = workbook.CreateFont(); - font18.FontName = "新細明體"; - font18.FontHeightInPoints = 18; - font18.IsBold = true; - ICellStyle styleTitle18 = workbook.CreateCellStyle(); - styleTitle18.SetFont(font18); - styleTitle18.Alignment = HorizontalAlignment.Center; - styleTitle18.VerticalAlignment = VerticalAlignment.Center; - ICellStyle styleLeft12 = workbook.CreateCellStyle(); - styleLeft12.SetFont(font12); - styleLeft12.Alignment = HorizontalAlignment.Left; - styleLeft12.VerticalAlignment = VerticalAlignment.Center; - ICellStyle styleLine12 = workbook.CreateCellStyle(); - styleLine12.SetFont(font12); - styleLine12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; - styleLine12.VerticalAlignment = VerticalAlignment.Center; - styleLine12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; - styleLine12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; - styleLine12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; - styleLine12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; - ICellStyle stylein12 = workbook.CreateCellStyle(); - stylein12.SetFont(font12Times); - stylein12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left; - stylein12.VerticalAlignment = VerticalAlignment.Center; - stylein12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; - stylein12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; - stylein12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; - stylein12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; - stylein12.WrapText = true; - #endregion - + using (FileStream templateStream = new FileStream(".\\template\\ElectricEachTotalCompare_temp.xlsx", FileMode.Open, FileAccess.Read)) { workbook = new XSSFWorkbook(templateStream); + + #region excel設定 + IFont font10 = workbook.CreateFont(); + font10.FontName = "標楷體"; + font10.FontHeightInPoints = 10; + ICellStyle greenCellStyle = workbook.CreateCellStyle(); + greenCellStyle.SetFont(font10); + greenCellStyle.Alignment = HorizontalAlignment.Center; + greenCellStyle.VerticalAlignment = VerticalAlignment.Center; + greenCellStyle.FillForegroundColor = IndexedColors.LightGreen.Index; + greenCellStyle.FillPattern = FillPattern.SolidForeground; + greenCellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; + greenCellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; + greenCellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; + greenCellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; + ICellStyle style12 = workbook.CreateCellStyle(); + style12.SetFont(font10); + style12.Alignment = HorizontalAlignment.Center; + style12.VerticalAlignment = VerticalAlignment.Center; + IFont font12Times = workbook.CreateFont(); + font12Times.FontName = "Times New Roman"; + font12Times.FontHeightInPoints = 12; + IFont font18 = workbook.CreateFont(); + font18.FontName = "標楷體"; + font18.FontHeightInPoints = 18; + font18.IsBold = true; + ICellStyle styleTitle18 = workbook.CreateCellStyle(); + styleTitle18.SetFont(font18); + styleTitle18.Alignment = HorizontalAlignment.Center; + styleTitle18.VerticalAlignment = VerticalAlignment.Center; + ICellStyle styleLeft12 = workbook.CreateCellStyle(); + styleLeft12.SetFont(font10); + styleLeft12.Alignment = HorizontalAlignment.Left; + styleLeft12.VerticalAlignment = VerticalAlignment.Center; + ICellStyle styleLine12 = workbook.CreateCellStyle(); + styleLine12.SetFont(font10); + styleLine12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; + styleLine12.VerticalAlignment = VerticalAlignment.Center; + styleLine12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; + styleLine12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; + styleLine12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; + styleLine12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; + ICellStyle stylein12 = workbook.CreateCellStyle(); + stylein12.SetFont(font12Times); + stylein12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left; + stylein12.VerticalAlignment = VerticalAlignment.Center; + stylein12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.WrapText = true; + + #endregion + var sheet = workbook.GetSheetAt(0); // 這裡假設您要使用第一個工作表 // 初始先填表格時間 @@ -895,49 +924,182 @@ namespace FrontendWebApi.ApiControllers cell.SetCellValue("明志科技大學" + start_year + "年" + start_month + "月份用電差異比較表"); row = sheet.GetRow(rowInit++) ?? sheet.CreateRow(rowInit++); + colInit = 0; cell = row.GetCell(colInit++) ?? row.CreateCell(colInit++); DateTime timeDay = date.AddMonths(1).AddDays(-1); // 用來記錄每個月的最後一天是幾月幾號 string timeRange = start_year + "." + start_month + ".01~" + timeDay.ToString("yyy.MM.dd"); cell.SetCellValue("電錶週期:" + timeRange); - row = sheet.GetRow(rowInit++) ?? sheet.CreateRow(rowInit++); - colInit = 3; - cell = row.GetCell(colInit++) ?? row.CreateCell(colInit++); - cell.SetCellValue("本月(A)\n" + start_year + "." + start_month); + //row = sheet.GetRow(rowInit++) ?? sheet.CreateRow(rowInit++); + //colInit = 3; + //cell = row.GetCell(colInit++) ?? row.CreateCell(colInit++); + //cell.SetCellValue("本月(A)\n" + start_year + "." + start_month); - cell = row.GetCell(colInit++) ?? row.CreateCell(colInit++); - DateTime previousMonth = date.AddMonths(-1); - string lastMonth = previousMonth.ToString("MM"); - cell.SetCellValue("上月(B)\n" + start_year + "." + lastMonth); + //cell = row.GetCell(colInit++) ?? row.CreateCell(colInit++); + //DateTime previousMonth = date.AddMonths(-1); + //string lastMonth = previousMonth.ToString("MM"); + //cell.SetCellValue("上月(B)\n" + start_year + "." + lastMonth); - cell = row.GetCell(colInit++) ?? row.CreateCell(colInit++); - cell.SetCellValue("上月差異(C)\n"); + //cell = row.GetCell(colInit++) ?? row.CreateCell(colInit++); + //cell.SetCellValue("上月差異(C)\n"); - cell = row.GetCell(colInit++) ?? row.CreateCell(colInit++); - DateTime previousYear = date.AddYears(-1); - string lastYear = previousYear.ToString("yyy"); - cell.SetCellValue("去年同期(D)\n" + lastYear + "." + start_month); + //cell = row.GetCell(colInit++) ?? row.CreateCell(colInit++); + //DateTime previousYear = date.AddYears(-1); + //string lastYear = previousYear.ToString("yyy"); + //cell.SetCellValue("去年同期(D)\n" + lastYear + "." + start_month); - cell = row.GetCell(colInit++) ?? row.CreateCell(colInit++); - cell.SetCellValue("上年差異(E)\n"); + //cell = row.GetCell(colInit++) ?? row.CreateCell(colInit++); + //cell.SetCellValue("上年差異(E)\n"); // 設定要填入資料的位置(rowIndex 和 columnIndex) int rowIndex = 4; // 假設要從第二列開始填入 int columnIndex = 1; // 假設第一欄是要填入的位置 + List need_cal_total = new List + { + "綜合大樓", + "體育舘", + "化工館", + "創新大樓", + "學人會館", + "綠能中心" + }; + List no_cal_sum_device = new List + { + "第一校區總盤", + "電機館分盤", + "第二校區總盤", + "薄膜分盤" + }; + int count_index = 1; + string last_build = ""; + string last_device = ""; + + // ------------------ + Dictionary> buildingSumData = new Dictionary>(); + #region 特定棟別總計處理 + foreach (var item in result_for_sum) + { + if (!need_cal_total.Contains(item.building_name)) + { + continue; + } + if (no_cal_sum_device.Exists(t => t == item.device_full_name)) + { + continue; + } + + foreach (var dataItem in item.rawData) + { + if (!buildingSumData.ContainsKey(item.building_name)) + { + buildingSumData[item.building_name] = new Dictionary(); + } + + if (!buildingSumData[item.building_name].ContainsKey(dataItem.timeStamp)) + { + buildingSumData[item.building_name][dataItem.timeStamp] = 0.0; + } + + buildingSumData[item.building_name][dataItem.timeStamp] += Math.Round(double.Parse(dataItem.avg_rawdata)); + } + } + #endregion + // 測試 + //foreach (var building in buildingSumData) + //{ + // Console.WriteLine($"Building: {building.Key}"); + // foreach (var timeStampData in building.Value) + // { + // Console.WriteLine($" TimeStamp: {timeStampData.Key}, Total Avg RawData: {timeStampData.Value}"); + // } + //} + // ------------------ foreach (var r in result) { - columnIndex = 1; - row = sheet.GetRow(rowIndex) ?? sheet.CreateRow(rowIndex); - + if (total_flag) + { + flag = false; + } string buildingName = r.building_name; string floorTag = r.floor_tag; + string deviceFullName = r.device_full_name; + columnIndex = 0; + + if (last_device == "電機館分盤") + { + flag = false; + } + + if (flag && buildingName == "化工館" && deviceFullName == "電機館分盤") + { + row = sheet.GetRow(rowIndex) ?? sheet.CreateRow(rowIndex); + cell = row.GetCell(columnIndex++) ?? row.CreateCell(columnIndex++); + cell.SetCellValue(count_index.ToString()); + count_index++; + columnIndex++; + + cell = row.GetCell(columnIndex++) ?? row.CreateCell(columnIndex++); + cell.SetCellValue(last_build + "總計"); + cell.CellStyle = greenCellStyle; + + foreach (var timeStampData in buildingSumData[last_build]) + { + cell = row.GetCell(columnIndex++) ?? row.CreateCell(columnIndex++); + cell.SetCellValue(timeStampData.Value); + } + + rowIndex++; + last_build = buildingName; + flag = false; + columnIndex = 0; + } + + if ((total_flag && need_cal_total.Contains(last_build)) || (flag && buildingName != last_build && need_cal_total.Contains(last_build))) + { + row = sheet.GetRow(rowIndex) ?? sheet.CreateRow(rowIndex); + cell = row.GetCell(columnIndex++) ?? row.CreateCell(columnIndex++); + cell.SetCellValue(count_index.ToString()); + count_index++; + + if (total_flag) + { + cell = row.GetCell(columnIndex) ?? row.CreateCell(columnIndex); + cell.SetCellValue(buildingName + floorTag); + } + columnIndex++; + + cell = row.GetCell(columnIndex++) ?? row.CreateCell(columnIndex++); + cell.SetCellValue(last_build + "總計"); + cell.CellStyle = greenCellStyle; + + foreach (var timeStampData in buildingSumData[last_build]) + { + cell = row.GetCell(columnIndex++) ?? row.CreateCell(columnIndex++); + cell.SetCellValue(timeStampData.Value.ToString()); + } + + rowIndex++; + last_build = buildingName; + + // continue; + } + + columnIndex = 0; + row = sheet.GetRow(rowIndex) ?? sheet.CreateRow(rowIndex); + cell = row.GetCell(columnIndex++) ?? row.CreateCell(columnIndex++); + cell.SetCellValue(count_index.ToString()); + count_index++; + cell = row.GetCell(columnIndex++) ?? row.CreateCell(columnIndex++); cell.SetCellValue(buildingName + floorTag); cell = row.GetCell(columnIndex++) ?? row.CreateCell(columnIndex++); - string deviceFullName = r.device_full_name; cell.SetCellValue(deviceFullName); + if (total_flag) + { + cell.CellStyle = greenCellStyle; + } foreach (var rawD in r.rawData) { @@ -946,11 +1108,12 @@ namespace FrontendWebApi.ApiControllers } rowIndex++; + last_build = buildingName; + last_device = deviceFullName; + flag = true; } } - // --- 8/24 修改到這裡囉 --- - var ms = new NpoiMemoryStream { AllowClose = false @@ -1034,7 +1197,7 @@ left join (select device_number, sum(kwh_result) kwh_sum from archive_electric_m left join (select device_number, sum(kwh_result) kwh_sum from archive_electric_meter_month where year(start_timestamp) = {last_year} and month(start_timestamp) = {start_month} group by device_number) d on a.device_number COLLATE utf8mb4_0900_ai_ci = d.device_number -- last Month join building e on a.device_building_tag = e.building_tag where {sqlWhere} -order by e.priority, a.priority"; +order by e.report_priority, a.priority"; Logger.LogInformation("SQL = " + sql + " building=" + input.building_tag + " floor_tag = " + input.floor_tag); var rawData = await backendRepository.GetAllAsync(sql); @@ -1057,7 +1220,7 @@ order by e.priority, a.priority"; { timeStamp = x.searchMT, // 或者是您所需的日期格式 device_number = x.device_number, - avg_rawdata = x.searchM + avg_rawdata = Math.Round(double.Parse(x.searchM)).ToString() }) ); l.rawData.AddRange( @@ -1067,7 +1230,7 @@ order by e.priority, a.priority"; { timeStamp = x.lastMT, // 或者是您所需的日期格式 device_number = x.device_number, - avg_rawdata = x.lastM + avg_rawdata = Math.Round(double.Parse(x.lastM)).ToString() }) ); l.rawData.AddRange( @@ -1077,7 +1240,7 @@ order by e.priority, a.priority"; { timeStamp = "last month different", // 或者是您所需的日期格式 device_number = x.device_number, - avg_rawdata = (double.Parse(x.searchM) - double.Parse(x.lastM)).ToString() + avg_rawdata = Math.Round((double.Parse(x.searchM) - double.Parse(x.lastM))).ToString() }) ); l.rawData.AddRange( @@ -1087,7 +1250,7 @@ order by e.priority, a.priority"; { timeStamp = x.lastYT, // 或者是您所需的日期格式 device_number = x.device_number, - avg_rawdata = x.lastY + avg_rawdata = Math.Round(double.Parse(x.lastY)).ToString() }) ); l.rawData.AddRange( @@ -1097,7 +1260,7 @@ order by e.priority, a.priority"; { timeStamp = "last year different", // 或者是您所需的日期格式 device_number = x.device_number, - avg_rawdata = (double.Parse(x.searchM) - double.Parse(x.lastY)).ToString() + avg_rawdata = Math.Round(double.Parse(x.searchM) - double.Parse(x.lastY), 2).ToString() }) ); @@ -1108,7 +1271,7 @@ order by e.priority, a.priority"; l.price = input.price.HasValue ? (Math.Round(input.price.Value, 2)).ToString() : Math.Round((await backendRepository.GetOneAsync("select system_value from variable where system_type = 'ElectricPrice' and deleted = 0")), 2).ToString(); - l.total_price = Math.Round((Decimal.Parse(l.total) * Decimal.Parse(l.price)), 2).ToString(); + l.total_price = Math.Round((Decimal.Parse(l.total) * Decimal.Parse(l.price))).ToString(); } apiResult.Code = "0000"; diff --git a/FrontendWebApi/template/ElectricEachTotalCompare_temp.xlsx b/FrontendWebApi/template/ElectricEachTotalCompare_temp.xlsx index 29bb6a6561325127912911f75a3ee1010b4a9715..c8f3032554d689cad1b93fdb5f4be073e6a80bbb 100644 GIT binary patch delta 6485 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 oc8WhLe!Wg8SS2 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