diff --git a/easydata.js/packs/core/src/i18n/i18n.ts b/easydata.js/packs/core/src/i18n/i18n.ts index ee72386b..c89a05e0 100644 --- a/easydata.js/packs/core/src/i18n/i18n.ts +++ b/easydata.js/packs/core/src/i18n/i18n.ts @@ -428,7 +428,10 @@ export namespace i18n { export function numberToStr(number: number, format?: string): string { if (format && format.length > 0) { const type = format.charAt(0); - if (['D', 'F', 'C'].indexOf(type) >= 0) { + if (type === 'S') { + return formatWithSequence(number, format.slice(1)); + } + else if (['D', 'F', 'C'].indexOf(type) >= 0) { const locale = getCurrentLocale(); return number.toLocaleString(locale, getNumberFromatOptions(format)); } @@ -442,11 +445,12 @@ export namespace i18n { } export function booleanToStr(bool: boolean, format?: string) { + if (format && format.length > 0) { const type = format.charAt(0); if (type === 'S') { const values = format.slice(1).split('|'); - if (values.length === 2) { + if (values.length > 1) { const value = values[(bool) ? 1 : 0]; return i18n.getText(value) || value; } @@ -455,6 +459,41 @@ export namespace i18n { return `${bool}`; } + const cachedSequenceFormats: { [format: string]: {[key: number]: string} } = {}; + + function formatWithSequence(number: number, format: string): string { + if (!cachedSequenceFormats[format]) { + + // parse and save in cache format values + const values = format.split('|') + .filter(v => v.length > 0) + .map(v => v.split('=')); + + cachedSequenceFormats[format] = {} + if (values.length > 0) { + if (values[0].length > 1) { + for (const value of values) { + cachedSequenceFormats[format][Number.parseInt(value[1])] = value[0]; + } + } + else { + values.forEach((value, index) => { + cachedSequenceFormats[format][index] = value[0]; + }); + } + } + + } + + const values = cachedSequenceFormats[format]; + if (values[number] !== undefined) { + const value = values[number]; + return i18n.getText(value) || value; + } + + return number.toString(); + } + function convertWithMask(number: number, mask: string) { let value = number.toString(); let result = ''; diff --git a/easydata.js/packs/ui/src/grid/easy_grid.ts b/easydata.js/packs/ui/src/grid/easy_grid.ts index 2f4997f3..33b163f0 100644 --- a/easydata.js/packs/ui/src/grid/easy_grid.ts +++ b/easydata.js/packs/ui/src/grid/easy_grid.ts @@ -670,7 +670,7 @@ export class EasyGrid { .catch(error => { console.error(error); return []; - });; + }); } protected renderFooter() { diff --git a/easydata.js/version.json b/easydata.js/version.json index 11a9cf04..eb31bd9b 100644 --- a/easydata.js/version.json +++ b/easydata.js/version.json @@ -1,5 +1,5 @@ { - "version": "1.2.5", - "baseVersion": "1.2.5", - "assetVersion": "01_02_05" + "version": "1.2.6", + "baseVersion": "1.2.6", + "assetVersion": "01_02_06" } diff --git a/easydata.net/src/EasyData.Core/DataUtils.cs b/easydata.net/src/EasyData.Core/DataUtils.cs index be56b352..a267fc04 100644 --- a/easydata.net/src/EasyData.Core/DataUtils.cs +++ b/easydata.net/src/EasyData.Core/DataUtils.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Text; namespace EasyData @@ -107,35 +108,55 @@ public static string ComposeKey(string parent, string child) /// public static DataType GetDataTypeBySystemType(Type systemType) { + if (systemType.IsEnum) + return GetDataTypeBySystemType(systemType.GetEnumUnderlyingType()); if (systemType == typeof(bool) || systemType == typeof(bool?)) return DataType.Bool; - else if (systemType == typeof(byte[])) + if (systemType == typeof(byte[])) return DataType.Blob; - else if (systemType == typeof(Guid)) + if (systemType == typeof(Guid)) return DataType.Guid; - else if (systemType == typeof(byte) || systemType == typeof(char) || systemType == typeof(sbyte) || systemType == typeof(byte?) || systemType == typeof(char?) || systemType == typeof(sbyte?)) + if (systemType == typeof(byte) || systemType == typeof(char) || systemType == typeof(sbyte) || systemType == typeof(byte?) || systemType == typeof(char?) || systemType == typeof(sbyte?)) return DataType.Byte; - else if (systemType == typeof(DateTime) || systemType == typeof(DateTime?) + if (systemType == typeof(DateTime) || systemType == typeof(DateTime?) || systemType == typeof(DateTimeOffset) || systemType == typeof(DateTimeOffset?)) return DataType.DateTime; - else if (systemType == typeof(TimeSpan) || systemType == typeof(TimeSpan?)) + if (systemType == typeof(TimeSpan) || systemType == typeof(TimeSpan?)) return DataType.Time; - else if (systemType == typeof(decimal) || systemType == typeof(decimal?)) + if (systemType == typeof(decimal) || systemType == typeof(decimal?)) return DataType.Currency; - else if (systemType == typeof(double) || systemType == typeof(Single) || systemType == typeof(float) || systemType == typeof(double?) || systemType == typeof(Single?) || systemType == typeof(float?)) + if (systemType == typeof(double) || systemType == typeof(Single) || systemType == typeof(float) || systemType == typeof(double?) || systemType == typeof(Single?) || systemType == typeof(float?)) return DataType.Float; - else if (systemType == typeof(short) || systemType == typeof(ushort) || systemType == typeof(short?) || systemType == typeof(ushort?)) + if (systemType == typeof(short) || systemType == typeof(ushort) || systemType == typeof(short?) || systemType == typeof(ushort?)) return DataType.Word; - else if (systemType == typeof(int) || systemType == typeof(uint) || systemType == typeof(int?) || systemType == typeof(uint?)) + if (systemType == typeof(int) || systemType == typeof(uint) || systemType == typeof(int?) || systemType == typeof(uint?)) return DataType.Int32; - else if (systemType == typeof(long) || systemType == typeof(ulong) || systemType == typeof(long?) || systemType == typeof(ulong?)) + if (systemType == typeof(long) || systemType == typeof(ulong) || systemType == typeof(long?) || systemType == typeof(ulong?)) return DataType.Int64; - else if (systemType == typeof(string)) + if (systemType == typeof(string)) return DataType.String; - else - return DataType.Unknown; + + return DataType.Unknown; } + /// + /// Builds sequence display format for enum. + /// + /// Type of the enum. + /// + public static string ComposeDisplayFormatForEnum(Type enumType) + { + if (!enumType.IsEnum) + return ""; + + var result = string.Join("|", enumType.GetFields() + .Where(f => f.Name != "value__") + .Select(f => $"{f.Name}={f.GetRawConstantValue()}")); + + return "{0:S" + result + "}"; + } + + /// /// Convert string representation in internal format to DateTime value. diff --git a/easydata.net/src/EasyData.Core/Formats/SequenceFormat.cs b/easydata.net/src/EasyData.Core/Formats/SequenceFormat.cs index c3957a86..9ac64220 100644 --- a/easydata.net/src/EasyData.Core/Formats/SequenceFormat.cs +++ b/easydata.net/src/EasyData.Core/Formats/SequenceFormat.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Text; +using System.Linq; namespace EasyData { @@ -9,15 +9,45 @@ public class SequenceFormat : IFormatProvider, ICustomFormatter { private readonly CultureInfo _culture; + private readonly string _format; - public SequenceFormat() : this(CultureInfo.InvariantCulture) + private readonly Dictionary _values; + + public SequenceFormat(string format) : this(format, CultureInfo.InvariantCulture) { - + } - public SequenceFormat(CultureInfo culture) + public SequenceFormat(string format, CultureInfo culture) { + if (!format.StartsWith("S")) + throw new FormatException(string.Format("The format of '{0}' is invalid.", format)); + + _format = format; _culture = culture; + _values = new Dictionary(); + + var keyValues = format.Substring(1) + .Split('|') + .Where(v => v != string.Empty) + .Select(v => v.Split('=')) + .ToArray(); + + if (keyValues.Length > 0) { + var containsKey = keyValues.First().Length == 2; + if (containsKey) { + foreach (var kv in keyValues) { + _values[long.Parse(kv[1])] = kv[0]; + } + } + else { + for (long i = 0; i < keyValues.Length; i++) { + _values[i] = keyValues[i][0]; + } + } + + } + } public object GetFormat(Type formatType) @@ -28,10 +58,21 @@ public object GetFormat(Type formatType) return null; } + private static HashSet _appliedTypes = new HashSet + { + typeof(bool), + typeof(sbyte), + typeof(byte), + typeof(int), + typeof(uint), + typeof(long), + typeof(ulong), + }; + public string Format(string fmt, object arg, IFormatProvider formatProvider) { // Provide default formatting if arg is not an Int64. - if (!fmt.StartsWith("S") || arg.GetType() != typeof(bool)) { + if (!fmt.StartsWith("S") || fmt != _format || !_appliedTypes.Contains(arg.GetType())) { try { return HandleOtherFormats(fmt, arg); } @@ -40,13 +81,17 @@ public string Format(string fmt, object arg, IFormatProvider formatProvider) } } - var values = fmt.Substring(1).Split('|'); - if (values.Length != 2) { - throw new FormatException(String.Format("The format of '{0}' is invalid.", fmt)); + if (arg is bool boolVal) { + if (_values.TryGetValue((boolVal) ? 1 : 0, out var result)) + return result; } - - var value = (bool)arg; - return values[(value) ? 1 : 0]; + else { + var longVal = (long)Convert.ChangeType(arg, typeof(long)); + if (_values.TryGetValue(longVal, out var result)) + return result; + } + + return arg.ToString(); } private string HandleOtherFormats(string format, object arg) diff --git a/easydata.net/src/EasyData.EntityFrameworkCore.Relational/MetaDataLoader/DbContextMetaDataLoader.cs b/easydata.net/src/EasyData.EntityFrameworkCore.Relational/MetaDataLoader/DbContextMetaDataLoader.cs index 1866a57b..06e507f9 100644 --- a/easydata.net/src/EasyData.EntityFrameworkCore.Relational/MetaDataLoader/DbContextMetaDataLoader.cs +++ b/easydata.net/src/EasyData.EntityFrameworkCore.Relational/MetaDataLoader/DbContextMetaDataLoader.cs @@ -167,6 +167,10 @@ protected virtual void ProcessNavigationProperty(MetaEntity entity, IEntityType lookUpAttr.PropInfo = navigation.PropertyInfo; + if (property.ClrType.IsEnum) { + lookUpAttr.DisplayFormat = DataUtils.ComposeDisplayFormatForEnum(property.ClrType); + } + var enabled = ApplyMetaEntityAttrAttribute(lookUpAttr, navigation.PropertyInfo); if (!enabled) return; @@ -272,6 +276,10 @@ protected virtual MetaEntityAttr CreateEntityAttribute(MetaEntity entity, IEntit entityAttr.IsNullable = property.IsNullable; + if (property.ClrType.IsEnum) { + entityAttr.DisplayFormat = DataUtils.ComposeDisplayFormatForEnum(property.ClrType); + } + var propInfo = property.PropertyInfo; if (propInfo != null) { if (propInfo.GetCustomAttribute(typeof(DisplayAttribute)) is DisplayAttribute displayAttr) { diff --git a/easydata.net/src/EasyData.Exporters.ClosedXML/Excel/ExcelDataExporter.cs b/easydata.net/src/EasyData.Exporters.ClosedXML/Excel/ExcelDataExporter.cs index 13191fa8..92f5da26 100644 --- a/easydata.net/src/EasyData.Exporters.ClosedXML/Excel/ExcelDataExporter.cs +++ b/easydata.net/src/EasyData.Exporters.ClosedXML/Excel/ExcelDataExporter.cs @@ -87,6 +87,9 @@ public async Task ExportAsync(IEasyDataResultSet data, Stream stream, IDataExpor { var mappedSettings = MapSettings(settings); + // predefined formatters + var predefinedFormatters = GetPredefinedFormatters(data.Cols, settings); + // replace forbidden symbols var r = new Regex(@"[\/\*\?:\[\]]"); var result = r.Replace(mappedSettings.Title ?? "", ""); @@ -143,7 +146,16 @@ Task WriteRowAsync(EasyDataRow row, bool isExtra = false, CancellationToken canc var dfmt = data.Cols[i].DisplayFormat; var type = data.Cols[i].Type; - ws.Cell($"{rowCellLetter}{cellNum}").Value = row[i] ?? ""; + + object value; + if (!string.IsNullOrEmpty(dfmt) && predefinedFormatters.TryGetValue(dfmt, out var provider)) { + value = string.Format(provider, dfmt, row[i]); + } + else { + value = row[i]; + } + + ws.Cell($"{rowCellLetter}{cellNum}").Value = value ?? ""; if (isExtra) ws.Cell($"{rowCellLetter}{cellNum}").Style.Font.Bold = true; rowCellLetter++; @@ -156,7 +168,8 @@ Task WriteRowAsync(EasyDataRow row, bool isExtra = false, CancellationToken canc return Task.CompletedTask; } - Func WriteExtraRowAsync = (extraRow, cancellationToken) => WriteRowAsync(extraRow, true, cancellationToken); + Func WriteExtraRowAsync = (extraRow, cancellationToken) + => WriteRowAsync(extraRow, true, cancellationToken); foreach (var row in data.Rows) { var add = settings?.RowFilter?.Invoke(row); @@ -185,18 +198,21 @@ Task WriteRowAsync(EasyDataRow row, bool isExtra = false, CancellationToken canc var dfmt = col.DisplayFormat; var colRange = ws.Range($"{letter}{endHeaderNum}:{letter}{cellNum}"); var dataType = MapDataType(type); - colRange.DataType = dataType; - if (type == DataType.Bool) { - colRange.Style.NumberFormat.Format = "\"True\";;\"False\";"; - } - if (dataType == XLDataType.DateTime) { - var format = Utils.GetDateFormat(type, mappedSettings, dfmt); - colRange.Style.DateFormat.Format = format; + if (!string.IsNullOrEmpty(dfmt) && predefinedFormatters.ContainsKey(dfmt)) { + colRange.DataType = XLDataType.Text; } - else if (!string.IsNullOrEmpty(dfmt)) { - var format = Utils.GetExcelDisplayFormat(mappedSettings, dfmt); - colRange.Style.NumberFormat.Format = format; + else { + colRange.DataType = dataType; + if (dataType == XLDataType.DateTime) { + var format = Utils.GetDateFormat(type, mappedSettings, dfmt); + colRange.Style.DateFormat.Format = format; + } + else if (!string.IsNullOrEmpty(dfmt)) { + var format = Utils.GetExcelDisplayFormat(mappedSettings, dfmt); + colRange.Style.NumberFormat.Format = format; + } } + colRange.Style.Alignment.Horizontal = MapAlignment(col.Style.Alignment); letter++; } @@ -240,6 +256,22 @@ Task WriteRowAsync(EasyDataRow row, bool isExtra = false, CancellationToken canc } } + private Dictionary GetPredefinedFormatters(IReadOnlyList cols, IDataExportSettings settings) + { + var result = new Dictionary(); + for (int i = 0; i < cols.Count; i++) { + var dfmt = cols[i].DisplayFormat; + if (!string.IsNullOrEmpty(dfmt) && !result.ContainsKey(dfmt)) { + var format = Utils.GetFormat(dfmt); + if (format.StartsWith("S")) { + result.Add(dfmt, new SequenceFormat(format, settings.Culture)); + } + } + + } + return result; + } + private static XLAlignmentHorizontalValues MapAlignment(ColumnAlignment alignment) { switch (alignment) { @@ -257,12 +289,13 @@ private static XLAlignmentHorizontalValues MapAlignment(ColumnAlignment alignmen private static XLDataType MapDataType(DataType type) { switch (type) { + case DataType.Bool: + return XLDataType.Boolean; case DataType.Date: case DataType.DateTime: return XLDataType.DateTime; case DataType.Time: return XLDataType.TimeSpan; - case DataType.Bool: case DataType.Byte: case DataType.Currency: case DataType.Int32: diff --git a/easydata.net/src/EasyData.Exporters.ClosedXML/Utils.cs b/easydata.net/src/EasyData.Exporters.ClosedXML/Utils.cs index f4dd93ec..8560e18f 100644 --- a/easydata.net/src/EasyData.Exporters.ClosedXML/Utils.cs +++ b/easydata.net/src/EasyData.Exporters.ClosedXML/Utils.cs @@ -11,6 +11,14 @@ internal static class Utils { private static Regex _formatRegex = new Regex("{0:(.*?)}", RegexOptions.Singleline); + public static string GetFormat(string displayFormat) + { + if (_formatRegex.IsMatch(displayFormat)) + return _formatRegex.Match(displayFormat).Groups[1].Value; + + return ""; + } + public static string GetExcelDisplayFormat(IDataExportSettings settings, string displayFormat) { if (_formatRegex.IsMatch(displayFormat)) { @@ -35,11 +43,7 @@ public static string GetExcelDisplayFormat(IDataExportSettings settings, string return floatFormat; } } - else if (type == 'S') { - var values = format.Substring(1).Split('|').Reverse(); - return string.Join(";", values.Select(v => $"\"{v}\";")); - } - + return format; }); } diff --git a/easydata.net/src/EasyData.Exporters.Default/Csv/CsvDataExporter.cs b/easydata.net/src/EasyData.Exporters.Default/Csv/CsvDataExporter.cs index beaa3978..af59b0b1 100644 --- a/easydata.net/src/EasyData.Exporters.Default/Csv/CsvDataExporter.cs +++ b/easydata.net/src/EasyData.Exporters.Default/Csv/CsvDataExporter.cs @@ -75,6 +75,9 @@ private async Task ExportAsync(IEasyDataResultSet data, TextWriter writer, IData var mappedSettings = MapSettings(settings); if (data == null) return; + // predefined formatters + var predefinedFormatters = GetPredefinedFormatters(data.Cols, settings); + if (settings.ShowDatasetInfo) { if (!string.IsNullOrEmpty(mappedSettings.Title)) { await writer.WriteLineAsync($"{mappedSettings.CommentCharacter} ").ConfigureAwait(false); @@ -109,7 +112,6 @@ private async Task ExportAsync(IEasyDataResultSet data, TextWriter writer, IData await writer.WriteLineAsync(val.ToString()).ConfigureAwait(false); } - async Task WriteRowAsync(EasyDataRow row, bool isExtra = false, CancellationToken cancellationToken = default) { var rowContent = new StringBuilder(); @@ -119,17 +121,27 @@ async Task WriteRowAsync(EasyDataRow row, bool isExtra = false, CancellationToke if (ignoredCols.Contains(i)) continue; - string dfmt = data.Cols[i].DisplayFormat; + var dfmt = data.Cols[i].DisplayFormat; DataType type = data.Cols[i].Type; if (i > 0) rowContent.Append(mappedSettings.Separator); - rowContent.Append(GetFormattedValue(row[i], type, mappedSettings, dfmt)); + + string value; + if (!string.IsNullOrEmpty(dfmt) && predefinedFormatters.TryGetValue(dfmt, out var provider)) { + value = string.Format(provider, dfmt, row[i]); + } + else { + value = GetFormattedValue(row[i], type, mappedSettings, dfmt); + } + + rowContent.Append(value); } await writer.WriteLineAsync(rowContent.ToString()).ConfigureAwait(false); } - Func WriteExtraRowAsync = (extraRow, cancellationToken) => WriteRowAsync(extraRow, true, cancellationToken); + Func WriteExtraRowAsync = (extraRow, cancellationToken) => + WriteRowAsync(extraRow, true, cancellationToken); foreach (var row in data.Rows) { @@ -151,6 +163,22 @@ async Task WriteRowAsync(EasyDataRow row, bool isExtra = false, CancellationToke await writer.FlushAsync().ConfigureAwait(false); } + private Dictionary GetPredefinedFormatters(IReadOnlyList cols, IDataExportSettings settings) + { + var result = new Dictionary(); + for (int i = 0; i < cols.Count; i++) { + var dfmt = cols[i].DisplayFormat; + if (!string.IsNullOrEmpty(dfmt) && !result.ContainsKey(dfmt)) { + var format = Utils.GetFormat(dfmt); + if (format.StartsWith("S")) { + result.Add(dfmt, new SequenceFormat(format, settings.Culture)); + } + } + + } + return result; + } + /// /// Gets the MIME content type of the exporting format. /// diff --git a/easydata.net/src/EasyData.Exporters.Default/Html/HtmlDataExporter.cs b/easydata.net/src/EasyData.Exporters.Default/Html/HtmlDataExporter.cs index febf0bae..68ccbf64 100644 --- a/easydata.net/src/EasyData.Exporters.Default/Html/HtmlDataExporter.cs +++ b/easydata.net/src/EasyData.Exporters.Default/Html/HtmlDataExporter.cs @@ -81,6 +81,9 @@ private async Task ExportAsync(IEasyDataResultSet data, TextWriter writer, IData var mappedSettings = MapSettings(settings); if (data == null) return; + // predefined formatters + var predefinedFormatters = GetPredefinedFormatters(data.Cols, settings); + await writer.WriteLineAsync("").ConfigureAwait(false); await writer.WriteLineAsync("").ConfigureAwait(false); await writer.WriteLineAsync("").ConfigureAwait(false); @@ -162,14 +165,22 @@ async Task RenderRowAsync(EasyDataRow row, bool isExtra = false, CancellationTok if (ignoredCols.Contains(i)) continue; - string dfmt = data.Cols[i].DisplayFormat; - DataType type = data.Cols[i].Type; - string s = GetFormattedValue(row[i], type, mappedSettings, dfmt); - if (mappedSettings.FixHtmlTags) - { - s = FixHtmlTags(s); + var dfmt = data.Cols[i].DisplayFormat; + var type = data.Cols[i].Type; + + string value; + if (!string.IsNullOrEmpty(dfmt) && predefinedFormatters.TryGetValue(dfmt, out var provider)) { + value = string.Format(provider, dfmt, row[i]); + } + else { + value = GetFormattedValue(row[i], type, mappedSettings, dfmt); + } + + if (mappedSettings.FixHtmlTags) { + value = FixHtmlTags(value); } - await writer.WriteLineAsync(string.Format("{0}", s)).ConfigureAwait(false); + + await writer.WriteLineAsync(string.Format("{0}", value)).ConfigureAwait(false); } await writer.WriteLineAsync("").ConfigureAwait(false); @@ -202,6 +213,22 @@ async Task RenderRowAsync(EasyDataRow row, bool isExtra = false, CancellationTok await writer.FlushAsync().ConfigureAwait(false); } + private Dictionary GetPredefinedFormatters(IReadOnlyList cols, IDataExportSettings settings) + { + var result = new Dictionary(); + for (int i = 0; i < cols.Count; i++) { + var dfmt = cols[i].DisplayFormat; + if (!string.IsNullOrEmpty(dfmt) && !result.ContainsKey(dfmt)) { + var format = Utils.GetFormat(dfmt); + if (format.StartsWith("S")) { + result.Add(dfmt, new SequenceFormat(format, settings.Culture)); + } + } + + } + return result; + } + /// /// Gets the MIME content type of the exporting format. /// diff --git a/easydata.net/src/EasyData.Exporters.Default/Utils.cs b/easydata.net/src/EasyData.Exporters.Default/Utils.cs index 41cb7a09..968c3b48 100644 --- a/easydata.net/src/EasyData.Exporters.Default/Utils.cs +++ b/easydata.net/src/EasyData.Exporters.Default/Utils.cs @@ -10,6 +10,14 @@ internal static class Utils { private static Regex _formatRegex = new Regex("{0:(.*?)}", RegexOptions.Singleline); + public static string GetFormat(string displayFormat) + { + if (_formatRegex.IsMatch(displayFormat)) + return _formatRegex.Match(displayFormat).Groups[1].Value; + + return ""; + } + public static string GetDateFormat(DataType dataType, IDataExportSettings settings, string displayFormat) { if (!string.IsNullOrEmpty(displayFormat)) { @@ -64,12 +72,7 @@ public static string GetFormattedValue(object val, DataType dataType, IDataExpor return string.Format(settings.Culture, "{0}", val); } - else if (val is bool) { - if (!string.IsNullOrEmpty(displayFormat)) - return string.Format(new SequenceFormat(settings.Culture), displayFormat, val); - } - - + return val.ToString(); } diff --git a/easydata.net/src/EasyData.Exporters.PdfSharp/Pdf/PdfDataExporter.cs b/easydata.net/src/EasyData.Exporters.PdfSharp/Pdf/PdfDataExporter.cs index 908f6ba8..ec02211b 100644 --- a/easydata.net/src/EasyData.Exporters.PdfSharp/Pdf/PdfDataExporter.cs +++ b/easydata.net/src/EasyData.Exporters.PdfSharp/Pdf/PdfDataExporter.cs @@ -123,6 +123,9 @@ public async Task ExportAsync(IEasyDataResultSet data, Stream stream, IDataExpor table.Borders.Right.Width = 0.5; table.Rows.LeftIndent = 0; + // predefined formatters + var predefinedFormatters = GetPredefinedFormatters(data.Cols, settings); + // filling columns //ignored columns @@ -144,8 +147,7 @@ public async Task ExportAsync(IEasyDataResultSet data, Stream stream, IDataExpor row.Format.Alignment = ParagraphAlignment.Center; row.Format.Font.Bold = true; row.Shading.Color = Color.FromRgb(0, 191, 255); - for (int i = 0; i < data.Cols.Count; i++) - { + for (int i = 0; i < data.Cols.Count; i++) { if (ignoredCols.Contains(i)) continue; @@ -181,14 +183,21 @@ Task WriteRowAsync(EasyDataRow row, bool isExtra = false, CancellationToken canc var col = data.Cols[i]; var dfmt = col.DisplayFormat; var type = col.Type; - var s = Utils.GetFormattedValue(row[i], type, mappedSettings, dfmt); + string value; + if (!string.IsNullOrEmpty(dfmt) && predefinedFormatters.TryGetValue(dfmt, out var provider)) { + value = string.Format(provider, dfmt, row[i]); + } + else { + value = Utils.GetFormattedValue(row[i], type, mappedSettings, dfmt); + } + pdfRow.Cells[i].Shading.Color = Color.FromRgb(255, 255, 255); pdfRow.Cells[i].VerticalAlignment = VerticalAlignment.Center; pdfRow.Cells[i].Format.Alignment = MapAlignment(col.Style.Alignment); pdfRow.Cells[i].Format.FirstLineIndent = 1; pdfRow.Cells[i].Format.Font.Bold = isExtra; - pdfRow.Cells[i].AddParagraph(s); + pdfRow.Cells[i].AddParagraph(value); table.SetEdge(0, 1, colsCount, 1, Edge.Box, BorderStyle.Single, 0.75); @@ -223,6 +232,22 @@ Task WriteRowAsync(EasyDataRow row, bool isExtra = false, CancellationToken canc } } + private Dictionary GetPredefinedFormatters(IReadOnlyList cols, IDataExportSettings settings) + { + var result = new Dictionary(); + for (int i = 0; i < cols.Count; i++) { + var dfmt = cols[i].DisplayFormat; + if (!string.IsNullOrEmpty(dfmt) && !result.ContainsKey(dfmt)) { + var format = Utils.GetFormat(dfmt); + if (format.StartsWith("S")) { + result.Add(dfmt, new SequenceFormat(format, settings.Culture)); + } + } + + } + return result; + } + private static ParagraphAlignment MapAlignment(ColumnAlignment alignment) { switch (alignment) { diff --git a/easydata.net/src/EasyData.Exporters.PdfSharp/Utils.cs b/easydata.net/src/EasyData.Exporters.PdfSharp/Utils.cs index 41cb7a09..7f7a77d5 100644 --- a/easydata.net/src/EasyData.Exporters.PdfSharp/Utils.cs +++ b/easydata.net/src/EasyData.Exporters.PdfSharp/Utils.cs @@ -10,6 +10,14 @@ internal static class Utils { private static Regex _formatRegex = new Regex("{0:(.*?)}", RegexOptions.Singleline); + public static string GetFormat(string displayFormat) + { + if (_formatRegex.IsMatch(displayFormat)) + return _formatRegex.Match(displayFormat).Groups[1].Value; + + return ""; + } + public static string GetDateFormat(DataType dataType, IDataExportSettings settings, string displayFormat) { if (!string.IsNullOrEmpty(displayFormat)) { @@ -64,12 +72,7 @@ public static string GetFormattedValue(object val, DataType dataType, IDataExpor return string.Format(settings.Culture, "{0}", val); } - else if (val is bool) { - if (!string.IsNullOrEmpty(displayFormat)) - return string.Format(new SequenceFormat(settings.Culture), displayFormat, val); - } - - + return val.ToString(); } diff --git a/easydata.net/version.json b/easydata.net/version.json index 75506844..21e4f584 100644 --- a/easydata.net/version.json +++ b/easydata.net/version.json @@ -1,5 +1,5 @@ { - "assemblyVersion": "1.2.5.0", - "packageVersion": "1.2.5", - "assetVersion": "01_02_05" + "assemblyVersion": "1.2.6.0", + "packageVersion": "1.2.6", + "assetVersion": "01_02_06" } \ No newline at end of file