From 69780e8aafd7a0e4d5ad2f6ab63767bf39106af1 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Fri, 24 Jun 2022 11:41:46 +0500 Subject: [PATCH] Add nullable support to CellAddress; Add example block --- .../Services/DailyReport/BlockAbstract.cs | 98 +++++++++++++++++++ .../Services/DailyReport/CellAddress.cs | 53 +++------- .../DailyReport/DailyReportMakerExcel.cs | 15 ++- .../DailyReport/SheetBlockAbstract.cs | 11 --- .../Services/DailyReport/XLExtentions.cs | 47 ++++++--- ConsoleApp1/Program.cs | 14 +++ ConsoleApp1/Properties/launchSettings.json | 8 -- 7 files changed, 178 insertions(+), 68 deletions(-) create mode 100644 AsbCloudInfrastructure/Services/DailyReport/BlockAbstract.cs delete mode 100644 AsbCloudInfrastructure/Services/DailyReport/SheetBlockAbstract.cs delete mode 100644 ConsoleApp1/Properties/launchSettings.json diff --git a/AsbCloudInfrastructure/Services/DailyReport/BlockAbstract.cs b/AsbCloudInfrastructure/Services/DailyReport/BlockAbstract.cs new file mode 100644 index 00000000..48e7702b --- /dev/null +++ b/AsbCloudInfrastructure/Services/DailyReport/BlockAbstract.cs @@ -0,0 +1,98 @@ +using AsbCloudApp.Data.DailyReportModel; +using ClosedXML.Excel; +using System.Linq; + +namespace AsbCloudInfrastructure.Services.DailyReport +{ + internal class BlockHeader : BlockAbstract + { + private readonly DailyReportHeadDto blockDto; + + public CellAddress AddressTitle { get; } + public CellAddress AddressCustomer { get; } + public CellAddress AddressDriller { get; } + public CellAddress AddressPeriod { get; } + public CellAddress AddressExampleData1 { get; } + public CellAddress[] AddressesExampleDataArray { get; } + + /// + /// Значение нижняя правая ячейка блока + /// + public override CellAddress AddressBlockBegin { get; } + + /// + /// Значение нижняя правая ячейка блока + /// + public override CellAddress AddressBlockEnd { get; } + + public BlockHeader(CellAddress addressBlockBegin, DailyReportHeadDto blockDto) + { + AddressBlockBegin = addressBlockBegin.Copy(); + + this.blockDto = blockDto; + AddressTitle = addressBlockBegin + (0, 0); + AddressCustomer = addressBlockBegin + (1,0); + AddressDriller = addressBlockBegin + (2, 0); + AddressPeriod = addressBlockBegin + (3, 0); + AddressExampleData1 = addressBlockBegin + (5, 0); + + AddressesExampleDataArray = new CellAddress[5]; + for (int i = 0; i < 5; i++) + AddressesExampleDataArray[i] = addressBlockBegin + (6 + i, 0); + + AddressBlockEnd = AddressesExampleDataArray.Last(); + } + + public override void Draw(IXLWorksheet sheet) + { + // значение в одну ячейку + sheet.Cell(AddressTitle) + ._SetValue($"Суточная сводка бурения скважины: {blockDto.WellName}, куст: {blockDto.ClusterName}") + .Style.SetH1(); + + // значение в несколько ячеек с объединением + sheet._Range(AddressCustomer, AddressCustomer + (0,7)) + ._SetValue($"Заказчик: {blockDto.Customer}"); + + sheet.Cell(AddressDriller) + ._SetValue($"Подрядчик: {blockDto.Contractor}"); + + sheet._Range(AddressExampleData1, AddressExampleData1 + (0, 4)) + ._SetValue(blockDto.BottomholeDepth); // для примера с будущей формулой + } + } + + internal class BlockWithFormula : BlockAbstract + { + private readonly BlockHeader blockHeader; + + public override CellAddress AddressBlockBegin { get; } + + public override CellAddress AddressBlockEnd { get; } + + public CellAddress AddressFomulaExample { get; set; } + + public BlockWithFormula(CellAddress addressBlockBegin, BlockHeader blockHeader) + { + AddressFomulaExample = addressBlockBegin + (0, 0); + AddressBlockBegin = addressBlockBegin.Copy(); + AddressBlockEnd = addressBlockBegin + (1, 0); + this.blockHeader = blockHeader; + } + + public override void Draw(IXLWorksheet sheet) + { + var formula = string.Format("{0}/5", blockHeader.AddressExampleData1.ToString()); + + sheet.Cell(AddressFomulaExample) + .SetFormulaA1(formula); + } + } + + internal abstract class BlockAbstract + { + public abstract CellAddress AddressBlockBegin { get; } + public abstract CellAddress AddressBlockEnd { get; } + public abstract void Draw(IXLWorksheet sheet); + } +} diff --git a/AsbCloudInfrastructure/Services/DailyReport/CellAddress.cs b/AsbCloudInfrastructure/Services/DailyReport/CellAddress.cs index eedf46ef..d6fb6bb9 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/CellAddress.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/CellAddress.cs @@ -5,6 +5,7 @@ using System.Text; namespace AsbCloudInfrastructure.Services.DailyReport { +#nullable enable internal class CellAddress: IXLAddress { const int excelLettersCount = 'Z' - 'A' + 1; @@ -22,56 +23,26 @@ namespace AsbCloudInfrastructure.Services.DailyReport public string UniqueId => ToString(XLReferenceStyle.A1, true); - public IXLWorksheet Worksheet { get; set; } + public IXLWorksheet? Worksheet { get; set; } - public CellAddress(int row, int colunm) + public CellAddress(IXLWorksheet? worksheet, int row, int colunm) { + Worksheet = worksheet; RowNumber = row; ColumnNumber = colunm; } public static CellAddress operator + (CellAddress a, CellAddress b) - => new CellAddress(a.RowNumber + b.RowNumber, a.ColumnNumber + b.ColumnNumber); + => new CellAddress(a.Worksheet, a.RowNumber + b.RowNumber, a.ColumnNumber + b.ColumnNumber); public static CellAddress operator +(CellAddress a, (int row, int column) b) - => new CellAddress(a.RowNumber + b.row, a.ColumnNumber + b.column); + => new CellAddress(a.Worksheet, a.RowNumber + b.row, a.ColumnNumber + b.column); public static CellAddress operator - (CellAddress a, CellAddress b) - => new CellAddress(a.RowNumber - b.RowNumber, a.ColumnNumber - b.ColumnNumber); + => new CellAddress(a.Worksheet, a.RowNumber - b.RowNumber, a.ColumnNumber - b.ColumnNumber); public static bool operator == (CellAddress a, CellAddress b) => a.RowNumber == b.RowNumber && a.ColumnNumber == b.ColumnNumber; public static bool operator !=(CellAddress a, CellAddress b) => !(a == b); - public static bool TryParse(string cellAddress, out CellAddress parsedAddress) - { - if (cellAddress.Length < 2) - { - parsedAddress = default; - return false; - } - - int row = 0; - int col = 0; - - for (int i = 0; i < cellAddress.Length; i++) - switch (cellAddress[i]) - { - case >= '0' and <= '9': - row = row * 10 + cellAddress[i] - '0'; - break; - case >= 'A' and <= 'Z': - col = col * excelLettersCount + cellAddress[i] - 'A'; - break; - case >= 'a' and <= 'z': - col = col * excelLettersCount + cellAddress[i] - 'a'; - break; - default: - parsedAddress = default; - return false; - } - parsedAddress = new CellAddress(row, col); - return true; - } - private string CalcColumnLetter() { string letter = ""; @@ -87,7 +58,14 @@ namespace AsbCloudInfrastructure.Services.DailyReport } public CellAddress Copy() - => new CellAddress(this.RowNumber, this.ColumnNumber); + => new CellAddress(Worksheet, RowNumber, ColumnNumber) + { + FixedColumn = this.FixedColumn, + FixedRow = this.FixedRow, + }; + + public override string ToString() + => ToString(XLReferenceStyle.A1); public string ToString(XLReferenceStyle referenceStyle) => ToString(referenceStyle, false); @@ -192,4 +170,5 @@ namespace AsbCloudInfrastructure.Services.DailyReport return false; } } +#nullable disable } diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportMakerExcel.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportMakerExcel.cs index dda6edd9..fc0b3da2 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportMakerExcel.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportMakerExcel.cs @@ -16,13 +16,26 @@ namespace AsbCloudInfrastructure.Services.DailyReport public Stream MakeReportFromBlocks(DailyReportHeadDto blockHead, DailyReportBhaDto blockBha, DailyReportDimensionlessDto blockDimensionless, DailyReportSaubDto blockSaub, DailyReportSignDto blockSign) { using var workbook = new XLWorkbook(); - FillSheet6blocks(workbook, blockHead, blockBha, blockDimensionless, blockSaub, blockSign); + FillExampleBlocks(workbook, blockHead); + //FillSheet6blocks(workbook, blockHead, blockBha, blockDimensionless, blockSaub, blockSign); MemoryStream memoryStream = new MemoryStream(); workbook.SaveAs(memoryStream, new SaveOptions { }); memoryStream.Seek(0, SeekOrigin.Begin); return memoryStream; } + private void FillExampleBlocks(XLWorkbook workbook, DailyReportHeadDto blockHeadDto) + { + var sheet = workbook.Worksheets.Add(blockHeadDto.ReportDate.ToString("dd.MM.yyyy")); + var addressStart = new CellAddress(sheet, 1, 1); + var blockHeader = new BlockHeader(addressStart, blockHeadDto); + addressStart = blockHeader.AddressBlockEnd + (1, 0); + var blockWithFormula = new BlockWithFormula(addressStart, blockHeader); + + blockHeader.Draw(sheet); + blockWithFormula.Draw(sheet); + } + private String converteCellCoordinate(int row, bool isCaps, int column) { var c = (Char)((isCaps ? 65 : 97) + (column - 1)); diff --git a/AsbCloudInfrastructure/Services/DailyReport/SheetBlockAbstract.cs b/AsbCloudInfrastructure/Services/DailyReport/SheetBlockAbstract.cs deleted file mode 100644 index e9d67cce..00000000 --- a/AsbCloudInfrastructure/Services/DailyReport/SheetBlockAbstract.cs +++ /dev/null @@ -1,11 +0,0 @@ -using ClosedXML.Excel; - -namespace AsbCloudInfrastructure.Services.DailyReport -{ - - internal abstract class SheetBlockAbstract - { - public abstract CellAddress Draw(IXLWorksheet sheet, CellAddress startPoint); - - } -} diff --git a/AsbCloudInfrastructure/Services/DailyReport/XLExtentions.cs b/AsbCloudInfrastructure/Services/DailyReport/XLExtentions.cs index 54cee75f..e114eb26 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/XLExtentions.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/XLExtentions.cs @@ -5,25 +5,26 @@ namespace AsbCloudInfrastructure.Services.DailyReport { internal static class XLExtentions { - public static IXLRange SetValue(this IXLRange range, object value) + public static IXLRange _SetValue(this IXLRange range, object value) { - range.Merge(); - range.FirstCell().SetValue(value); - return range; + var mergedRange = range.Merge(); + mergedRange.FirstCell()._SetValue(value); + mergedRange.Style.SetAllBorders(); + return mergedRange; } - public static IXLCell SetValue(this IXLCell cell, object value) + public static IXLCell _SetValue(this IXLCell cell, object value) { switch (value) { case DateTime dateTime: - cell.SetValue(dateTime); + cell._SetValue(dateTime); break; case IFormattable formattable: - cell.SetValue(formattable); + cell._SetValue(formattable); break; case string valueString: - cell.SetValue(valueString); + cell._SetValue(valueString); break; default: cell.Value = value; @@ -33,7 +34,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport return cell; } - public static IXLCell SetValue(this IXLCell cell, string value, bool adaptRowHeight = false) + public static IXLCell _SetValue(this IXLCell cell, string value, bool adaptRowHeight = false) { cell.Value = value; cell.Style @@ -57,7 +58,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport return cell; } - public static IXLCell SetValue(this IXLCell cell, DateTime value, string dateFormat = "DD.MM.YYYY HH:MM:SS") + public static IXLCell _SetValue(this IXLCell cell, DateTime value, string dateFormat = "DD.MM.YYYY HH:MM:SS") { cell.Value = value; cell.Style @@ -72,7 +73,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport return cell; } - public static IXLCell SetValue(this IXLCell cell, IFormattable value, string format = "0.00") + public static IXLCell _SetValue(this IXLCell cell, IFormattable value, string format = "0.00") { cell.Value = value; cell.Style @@ -97,5 +98,29 @@ namespace AsbCloudInfrastructure.Services.DailyReport style.Border.OutsideBorder = borderStyle; return style; } + + public static IXLStyle SetBaseFont(this IXLStyle style) + { + style.Font.FontName = "Calibri"; + style.Font.FontSize = 10; + return style; + } + + public static IXLStyle SetH1(this IXLStyle style) + { + style.Font.FontName = "Calibri"; + style.Font.FontSize = 14; + return style; + } + + /// + /// Костыль исправляющий проблему в библиотеке IXLRange Range(this IXLWorksheet, IXLAddress, IXLAddress) с кастингом IXLAddress к XLAddress. + /// + /// + /// + /// + /// + public static IXLRange _Range(this IXLWorksheet sheet, CellAddress begin, CellAddress end) + => sheet.Range(begin.RowNumber, begin.ColumnNumber, end.RowNumber, end.ColumnNumber); } } diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index 61cbf11e..f9b90761 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -1,5 +1,6 @@ using AsbCloudApp.Data.DailyReportModel; using AsbCloudInfrastructure.EfCache; +using AsbCloudInfrastructure.Services.DailyReport; using ClosedXML.Excel; using System; using System.IO; @@ -27,6 +28,19 @@ namespace ConsoleApp1 WellDepthIntervalStartDate= 26.5, BottomholeDepth= 66.6 }; + + //------------- example ----------------- + var service = new DailyReportMakerExcel(); + var stream = service.MakeReportFromBlocks(block, null, null, null, null); + var filename = "____.xlsx"; + if (File.Exists(filename)) + File.Delete(filename); + using var fileStream = File.OpenWrite(filename); + stream.CopyTo(fileStream); + + return; + //------------- end of example ----------------- + var block2 = new DailyReportBhaDto() { BHADescription="sadasdasdasdasdasdjlaskjdaksjdlasdlalskdklj" diff --git a/ConsoleApp1/Properties/launchSettings.json b/ConsoleApp1/Properties/launchSettings.json deleted file mode 100644 index 33504c94..00000000 --- a/ConsoleApp1/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "WSL": { - "commandName": "WSL2", - "distributionName": "" - } - } -} \ No newline at end of file