diff --git a/Demos/OpenSource/FastReport.OpenSource.MVC/FastReport.OpenSource.MVC.csproj b/Demos/OpenSource/FastReport.OpenSource.MVC/FastReport.OpenSource.MVC.csproj index 9861d68f..57005de9 100644 --- a/Demos/OpenSource/FastReport.OpenSource.MVC/FastReport.OpenSource.MVC.csproj +++ b/Demos/OpenSource/FastReport.OpenSource.MVC/FastReport.OpenSource.MVC.csproj @@ -1,6 +1,6 @@ - netcoreapp2.0 + netcoreapp2.1 true aspnet-FastReport.OpenSource.MVC-A0035279-FE70-4D27-A6A9-1F1B33906C98 docker-compose.dcproj @@ -16,7 +16,7 @@ - + diff --git a/Demos/OpenSource/FastReport.OpenSource.Web.MVC/FastReport.OpenSource.Web.MVC.csproj b/Demos/OpenSource/FastReport.OpenSource.Web.MVC/FastReport.OpenSource.Web.MVC.csproj index 674dd622..a8d62b12 100644 --- a/Demos/OpenSource/FastReport.OpenSource.Web.MVC/FastReport.OpenSource.Web.MVC.csproj +++ b/Demos/OpenSource/FastReport.OpenSource.Web.MVC/FastReport.OpenSource.Web.MVC.csproj @@ -1,11 +1,11 @@ - netcoreapp2.0 + netcoreapp2.1 - + diff --git a/Demos/OpenSource/PdfExport/PdfExport.csproj b/Demos/OpenSource/PdfExport/PdfExport.csproj index 686e5a6c..a5d6f2c4 100644 --- a/Demos/OpenSource/PdfExport/PdfExport.csproj +++ b/Demos/OpenSource/PdfExport/PdfExport.csproj @@ -2,13 +2,13 @@ Exe - netcoreapp2.2 + netcoreapp2.1 - + diff --git a/Demos/Reports/Barcode.frx b/Demos/Reports/Barcode.frx index a2387a00..9008f539 100644 --- a/Demos/Reports/Barcode.frx +++ b/Demos/Reports/Barcode.frx @@ -1,74 +1,75 @@  - + - + - + - - - - - - - - + + + + + + + - - + + - - + + - - - - - - - - - + + + + + + + + + - - - - + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + + + + diff --git a/Demos/Reports/QR-Codes.frx b/Demos/Reports/QR-Codes.frx index 14f8994e..1b5901de 100644 --- a/Demos/Reports/QR-Codes.frx +++ b/Demos/Reports/QR-Codes.frx @@ -1,13 +1,12 @@  - + - - + @@ -26,13 +25,16 @@ - - + + - - + + + + + - + diff --git a/Extras/Core/FastReport.Data/FastReport.Data.MongoDB/FastReport.Core.Data.MongoDB.csproj b/Extras/Core/FastReport.Data/FastReport.Data.MongoDB/FastReport.Core.Data.MongoDB.csproj index d59b456f..3d062732 100644 --- a/Extras/Core/FastReport.Data/FastReport.Data.MongoDB/FastReport.Core.Data.MongoDB.csproj +++ b/Extras/Core/FastReport.Data/FastReport.Data.MongoDB/FastReport.Core.Data.MongoDB.csproj @@ -1,6 +1,6 @@  - netstandard2.0;net4.5 + netstandard2.0;net4.5;net4.5.2 false ../../../FastReport.Plugins.snk true @@ -23,10 +23,15 @@ FRCORE; - - - - + + + + + + + + + diff --git a/Extras/Core/FastReport.Data/FastReport.Data.MongoDB/FastReport.OpenSource.Data.MongoDB.csproj b/Extras/Core/FastReport.Data/FastReport.Data.MongoDB/FastReport.OpenSource.Data.MongoDB.csproj index 5f94038f..47cfce7d 100644 --- a/Extras/Core/FastReport.Data/FastReport.Data.MongoDB/FastReport.OpenSource.Data.MongoDB.csproj +++ b/Extras/Core/FastReport.Data/FastReport.Data.MongoDB/FastReport.OpenSource.Data.MongoDB.csproj @@ -1,6 +1,6 @@ - netstandard2.0;net4.5 + netstandard2.0;net4.5;net4.5.2 false ../../../FastReport.Plugins.snk true @@ -24,11 +24,16 @@ FRCORE; - - - - - + + + + + + + + + + @@ -49,9 +54,4 @@ - - - - - diff --git a/Extras/Core/FastReport.Data/FastReport.Data.MongoDB/MongoDBDataConnection.cs b/Extras/Core/FastReport.Data/FastReport.Data.MongoDB/MongoDBDataConnection.cs index faad9dd3..069d7098 100644 --- a/Extras/Core/FastReport.Data/FastReport.Data.MongoDB/MongoDBDataConnection.cs +++ b/Extras/Core/FastReport.Data/FastReport.Data.MongoDB/MongoDBDataConnection.cs @@ -5,6 +5,7 @@ using System.Data; using MongoDB.Bson; using FastReport.Data; +using MongoDB.Driver.Core.Configuration; namespace FastReport.Data { @@ -44,12 +45,21 @@ private void ExecuteFillDataTable(BsonDocument doc, DataTable dt, DataRow dr, st #endregion #region Protected Methods - + /// protected DataTable CreateDataTable(DataTable table, bool allRows) { MongoClient client = new MongoClient(ConnectionString); - IMongoDatabase db = client.GetDatabase(dbName); + IMongoDatabase db = null; + if (dbName != string.Empty) + { + db = client.GetDatabase(dbName); + } + else + { + MongoUrlBuilder builder = new MongoUrlBuilder(ConnectionString); + db = client.GetDatabase(builder.DatabaseName); + } var collection = db.GetCollection(table.TableName); if (!allRows) @@ -76,7 +86,17 @@ protected override string GetConnectionStringWithLoginInfo(string userName, stri MongoUrlBuilder builder = new MongoUrlBuilder(ConnectionString); builder.Username = userName; builder.Password = password; - return builder.ToString(); +#if NET45 + string url = builder.ToString(); + if(builder.Scheme == ConnectionStringScheme.MongoDBPlusSrv && builder.Server.Port != 27017) + { + string portString = builder.Server.Port.ToString(); + url = url.Remove(url.IndexOf(portString) - 1, 1).Replace(portString, ""); + } + return url; +#else + return builder.ToMongoUrl().Url; +#endif } #endregion diff --git a/FastReport.Base/BandBase.cs b/FastReport.Base/BandBase.cs index afefc3cf..b85bbd9f 100644 --- a/FastReport.Base/BandBase.cs +++ b/FastReport.Base/BandBase.cs @@ -963,7 +963,10 @@ public override bool Break(BreakableComponent breakTo) public override void GetData() { base.GetData(); - foreach (ReportComponentBase obj in Objects) + + FRCollectionBase list = new FRCollectionBase(); + Objects.CopyTo(list); + foreach (ReportComponentBase obj in list) { obj.GetData(); obj.OnAfterData(); @@ -1025,7 +1028,7 @@ public void OnAfterLayout(EventArgs e) InvokeEvent(AfterLayoutEvent, e); } - #endregion +#endregion /// /// Initializes a new instance of the class with default settings. diff --git a/FastReport.Base/Barcode/Barcode2DBase.cs b/FastReport.Base/Barcode/Barcode2DBase.cs index 162e8d5a..551fcbc8 100644 --- a/FastReport.Base/Barcode/Barcode2DBase.cs +++ b/FastReport.Base/Barcode/Barcode2DBase.cs @@ -13,14 +13,14 @@ namespace FastReport.Barcode public abstract class Barcode2DBase : BarcodeBase { private static Font FFont = new Font("Arial", 8); - - private void DrawBarcode(IGraphicsRenderer g, float width, float height) - { - SizeF originalSize = CalcBounds(); - float kx = width / originalSize.Width; - float ky = height / originalSize.Height; - Draw2DBarcode(g, kx, ky); + private void DrawBarcode(IGraphicsRenderer g, float width, float height) + { + SizeF originalSize = CalcBounds(); + float kx = width / originalSize.Width; + float ky = height / originalSize.Height; + + Draw2DBarcode(g, kx, ky); //If swiss qr, draw the swiss cross if (text.StartsWith("SPC")) @@ -31,22 +31,30 @@ private void DrawBarcode(IGraphicsRenderer g, float width, float height) g.FillRectangle(Brushes.White, width / 2 - width / 100f * 4, top / 2 - top / 100 * 1.5f, width / 100f * 8, top / 100 * 3); g.FillRectangle(Brushes.White, width / 2 - width / 100f * 1.5f, top / 2 - top / 100 * 4, width / 100f * 3, top / 100 * 8); } + if (text.StartsWith("ST")) + { + Pen skyBluePen = new Pen(Brushes.Black); + skyBluePen.Width = (kx * 4 * zoom) / 2; + + g.DrawLine(skyBluePen, width - 2, height / 2, width - 2, height - 2); + g.DrawLine(skyBluePen, width / 2, height - 2, width - 2, height - 2); + } // draw the text. - if (showText) - { - string data = StripControlCodes(text); - if (data.Length > 0) - { - // When we print, .Net automatically scales the font. However, we need to handle this process. - // Downscale the font to the screen resolution, then scale by required value (ky). - float fontZoom = 18f / (int)g.MeasureString(data, FFont).Height * ky; - using (Font drawFont = new Font(FFont.Name, FFont.Size * fontZoom, FFont.Style)) + if (showText) { - g.DrawString(data, drawFont, Brushes.Black, new RectangleF(0, height - 18 * ky, width, 18 * ky)); + string data = StripControlCodes(text); + if (data.Length > 0) + { + // When we print, .Net automatically scales the font. However, we need to handle this process. + // Downscale the font to the screen resolution, then scale by required value (ky). + float fontZoom = 18f / (int)g.MeasureString(data, FFont).Height * ky; + using (Font drawFont = new Font(FFont.Name, FFont.Size * fontZoom, FFont.Style)) + { + g.DrawString(data, drawFont, Brushes.Black, new RectangleF(0, height - 18 * ky, width, 18 * ky)); + } + } } } - } - } internal virtual void Draw2DBarcode(IGraphicsRenderer g, float kx, float ky) { diff --git a/FastReport.Base/Barcode/Barcode2of5.cs b/FastReport.Base/Barcode/Barcode2of5.cs index e18ee9d9..92ede0fd 100644 --- a/FastReport.Base/Barcode/Barcode2of5.cs +++ b/FastReport.Base/Barcode/Barcode2of5.cs @@ -86,7 +86,26 @@ public class BarcodeDeutscheIdentcode : Barcode2of5Interleaved [System.ComponentModel.Category("Appearance")] public bool PrintCheckSum { get; set; } - #endregion + #endregion + + private string CheckSumModulo10(string data) + { + int sum = 0; + int fak = data.Length; + + for (int i = 0; i < data.Length; i++) + { + if ((fak % 2) == 0) + sum += int.Parse(data[i].ToString()) * 9; + else + sum += int.Parse(data[i].ToString()) * 4; + fak--; + } + + if ((sum % 10) == 0) + return data + "0"; + return data + (10 - (sum % 10)).ToString(); + } internal override string GetPattern() { @@ -97,7 +116,7 @@ internal override string GetPattern() if(CalcCheckSum) { if (text.Length == 11) - text = DoCheckSumming(text); + text = CheckSumModulo10(text); else if (text.Length != 12) throw new Exception(Res.Get("Messages,BarcodeLengthMismatch")); @@ -170,7 +189,122 @@ public BarcodeDeutscheIdentcode() } } + /// + /// Generates the "Deutsche Leitcode" barcode. + /// + public class BarcodeDeutscheLeitcode : Barcode2of5Interleaved + { + #region Properties + /// + /// Gets or sets a value that indicates that CheckSum should be printed. + /// + [System.ComponentModel.DefaultValue(true)] + [System.ComponentModel.Category("Appearance")] + public bool PrintCheckSum { get; set; } + + private string CheckSumModulo10(string data) + { + int sum = 0; + int fak = data.Length; + + for (int i = 0; i < data.Length; i++) + { + if ((fak % 2) == 0) + sum += int.Parse(data[i].ToString()) * 9; + else + sum += int.Parse(data[i].ToString()) * 4; + fak--; + } + + if ((sum % 10) == 0) + return data + "0"; + return data + (10 - (sum % 10)).ToString(); + } + + + #endregion + internal override void Serialize(FRWriter writer, string prefix, BarcodeBase diff) + { + base.Serialize(writer, prefix, diff); + BarcodeDeutscheLeitcode c = diff as BarcodeDeutscheLeitcode; + + if (c == null || PrintCheckSum != c.PrintCheckSum) + writer.WriteValue(prefix + "DrawVerticalBearerBars", PrintCheckSum); + } + /// + public override void Assign(BarcodeBase source) + { + base.Assign(source); + + BarcodeDeutscheLeitcode src = source as BarcodeDeutscheLeitcode; + PrintCheckSum = src.PrintCheckSum; + } + + internal override string GetPattern() + { + string result = "5050"; //Startcode + string c; + string text = base.text.Replace(".", "").Replace(" ", ""); + + if (CalcCheckSum) + { + if (text.Length == 13) + text = CheckSumModulo10(text); + else if (text.Length != 14) + throw new Exception(Res.Get("Messages,BarcodeLengthMismatch")); + + } + else + { + if (text.Length != 14) + throw new Exception(Res.Get("Messages,BarcodeLengthMismatch")); + } + + for (int i = 0; i < (text.Length / 2); i++) + { + for (int j = 0; j <= 4; j++) + { + if (tabelle_2_5[CharToInt(text[i * 2]), j] == 1) + c = "6"; + else + c = "5"; + result += c; + + if (tabelle_2_5[CharToInt(text[i * 2 + 1]), j] == 1) + c = "1"; + else + c = "0"; + result += c; + } + } + + result += "605"; // Stopcode + + base.text = text + .Insert(5, ".") + .Insert(6, " ") + .Insert(10, ".") + .Insert(11, " ") + .Insert(15, ".") + .Insert(16, " ") + .Insert(19, " "); + + + + return result; + } + + public BarcodeDeutscheLeitcode() + { + ratioMin = 2.25F; + ratioMax = 3.5F; + WideBarRatio = 3F; + CalcCheckSum = true; + } + + + } /// /// Generates the "ITF-14" barcode. /// diff --git a/FastReport.Base/Barcode/BarcodeObject.cs b/FastReport.Base/Barcode/BarcodeObject.cs index 830de168..4c427ab8 100644 --- a/FastReport.Base/Barcode/BarcodeObject.cs +++ b/FastReport.Base/Barcode/BarcodeObject.cs @@ -657,9 +657,10 @@ public BarcodeItem(Type objType, string barcodeName) new BarcodeItem(typeof(Barcode2of5Industrial), "2/5 Industrial"), new BarcodeItem(typeof(Barcode2of5Matrix), "2/5 Matrix"), new BarcodeItem(typeof(BarcodeDeutscheIdentcode), "Deutsche Identcode"), + new BarcodeItem(typeof(BarcodeDeutscheLeitcode),"Deutshe Leitcode"), new BarcodeItem(typeof(BarcodeITF14), "ITF-14"), new BarcodeItem(typeof(BarcodeCodabar), "Codabar"), - new BarcodeItem(typeof(Barcode128), "Code128"), + new BarcodeItem(typeof(Barcode128), "Code128"), new BarcodeItem(typeof(Barcode39), "Code39"), new BarcodeItem(typeof(Barcode39Extended), "Code39 Extended"), new BarcodeItem(typeof(Barcode93), "Code93"), diff --git a/FastReport.Base/Barcode/QRCode/QRData.cs b/FastReport.Base/Barcode/QRCode/QRData.cs index 62a2c189..e70b4bb8 100644 --- a/FastReport.Base/Barcode/QRCode/QRData.cs +++ b/FastReport.Base/Barcode/QRCode/QRData.cs @@ -1,6 +1,7 @@ using FastReport.Utils; using System; using System.Collections.Generic; +using System.Security.Policy; using System.Text; using System.Text.RegularExpressions; @@ -49,6 +50,8 @@ public static QRData Parse(string data) return new QREmailAddress(data); else if (data.StartsWith("SPC")) return new QRSwiss(data); + else if (data.StartsWith("ST")) + return new QRSberBank(data); else return new QRText(data); } @@ -215,6 +218,320 @@ public override void Unpack(string data) } } + class QRSberBank : QRData + { + char Separator = '|'; + + private string FormatIdentifier="ST"; + public string VersionStandart = "0001"; + public string Encoding="2"; + + #region necessary payment details + public string Name; + public string PersonalAcc; + public string BankName; + public string BIC; + public string CorrespAcc; + #endregion + + #region Additional payment info + public string Sum; + public string Purpose; + public string PayeeINNB; + public string PayerINN; + public string DrawerStatus; + public string KPP; + public string CBC; + public string OKTMO; + public string PaytReason; + public string TaxPeriod; + public string DocNo; + public DateTime DocDate; + public string TaxPaytKind; + #endregion + + #region Another additional payment info + public string LastName; + public string FirstName; + public string MiddleName; + public string PayerAddress; + public string PersonalAccount; + public string DocIdx; + public string PensAcc; + public string Contract; + public string PersAccp; + public string Flat; + public string Phone; + public string PayerIdType; + public string PayerIdNum; + public string ChildFio; + public DateTime BirthDate; + public DateTime PaymTerm; + public string PaymPeriod; + public string Category; + public string ServiceName; + public string CounterId; + public string CounterVal; + public string QuittId; + public DateTime QuittDate; + public string InstNum; + public string ClassNum; + public string SpecFio; + public string AddAmount; + public string RuleId; + public string ExecId; + public string RegType; + public string UIN; + public string TechCode; //specify numbers somewhere + #endregion + + public QRSberBank() : base() { } + public QRSberBank(string data) : base(data) { } + public override string Pack() + { + string result = FormatIdentifier; + result += VersionStandart; + result += Encoding; + result += Separator + "Name=" + Name; + result += Separator + "PersonalAcc=" + PersonalAcc; + result += Separator + "BankName=" + BankName; + result += Separator + "BIC=" + BIC; + result += Separator + "CorrespAcc=" + CorrespAcc; + if (!String.IsNullOrWhiteSpace(Sum)) result += Separator + "Sum=" + Sum; + if (!String.IsNullOrWhiteSpace(Purpose)) result += Separator + "Purpose=" + Purpose; + if (!String.IsNullOrWhiteSpace(PayeeINNB)) result += Separator + "PayeeINN=" + PayeeINNB; + if (!String.IsNullOrWhiteSpace(PayerINN)) result += Separator + "PayerINN=" + PayerINN; + if (!String.IsNullOrWhiteSpace(DrawerStatus)) result += Separator + "DrawerStatus=" + DrawerStatus; + if (!String.IsNullOrWhiteSpace(KPP)) result += Separator+ "KPP=" + KPP; + if(!String.IsNullOrWhiteSpace(CBC)) result += Separator+"CBC="+CBC; + if (!String.IsNullOrWhiteSpace(OKTMO)) result += Separator + "OKTMO=" + OKTMO; + if (!String.IsNullOrWhiteSpace(PaytReason)) result += Separator + "PaytReason="+PaytReason; + if (!String.IsNullOrWhiteSpace(TaxPeriod)) result += Separator +"TaxPeriod="+TaxPeriod; + if (!String.IsNullOrWhiteSpace(DocNo)) result += Separator +"DocNo="+DocNo; + if (DocDate != DateTime.MinValue) + { + result += Separator + "DocDate=" + DocDate.ToString("MM.dd.yyyy"); + } + if (!String.IsNullOrWhiteSpace(TaxPaytKind)) result += Separator + "TaxPaytKind=" + TaxPaytKind; + if (!String.IsNullOrWhiteSpace(LastName)) result += Separator + "LastName=" + LastName; + if (!String.IsNullOrWhiteSpace(FirstName)) result += Separator +"FirstName="+FirstName; + if (!String.IsNullOrWhiteSpace(MiddleName)) result += Separator +"MiddleName="+MiddleName; + if (!String.IsNullOrWhiteSpace(PayerAddress)) result += Separator +"PayerAddress="+PayerAddress; + if (!String.IsNullOrWhiteSpace(PersonalAccount)) result += Separator +"PersonalAccount="+PersonalAccount; + if (!String.IsNullOrWhiteSpace(DocIdx)) result += Separator + "DocIdx="+DocIdx; + if (!String.IsNullOrWhiteSpace(PensAcc)) result += Separator +"PensAcc="+PensAcc; + if (!String.IsNullOrWhiteSpace(Contract)) result += Separator +"Contract="+Contract; + if (!String.IsNullOrWhiteSpace(PersAccp)) result += Separator +"PersAcc="+PersAccp; + if (!String.IsNullOrWhiteSpace(Flat)) result += Separator +"Flat="+Flat; + if (!String.IsNullOrWhiteSpace(Phone)) result += Separator + "Phone=" + Phone; + if (!String.IsNullOrWhiteSpace(PayerIdType)) result += Separator +"PayerIdType="+PayerIdType; + if (!String.IsNullOrWhiteSpace(PayerIdNum)) result += Separator +"PayerIdNum="+PayerIdNum; + if (!String.IsNullOrWhiteSpace(ChildFio)) result += Separator +"ChildFio="+ChildFio; + if (BirthDate != DateTime.MinValue) + { + result+=Separator+"BirthDate="+BirthDate.ToString("MM.dd.yyyy"); + } + if (PaymTerm!=DateTime.MinValue) + { + result+=Separator+"PaymTerm="+PaymTerm.ToString("MM.dd.yyyy"); + } + if (!String.IsNullOrWhiteSpace(PaymPeriod)) result += Separator +"PaymPeriod="+PaymPeriod; + if (!String.IsNullOrWhiteSpace(Category)) result += Separator + "Category=" + Category; + if (!String.IsNullOrWhiteSpace(ServiceName)) result += Separator + "ServiceName=" + ServiceName; + if (!String.IsNullOrWhiteSpace(CounterId)) result += Separator + "CounterId=" + CounterId; + if (!String.IsNullOrWhiteSpace(CounterVal)) result += Separator + "CounterVal=" + CounterVal; + if (!String.IsNullOrWhiteSpace(QuittId)) result += Separator + "QuittId=" + QuittId; + if (QuittDate != DateTime.MinValue) + { + result+=Separator+"QuittDate="+QuittDate.ToString("MM.dd.yyyy"); + } + if (!String.IsNullOrWhiteSpace(InstNum)) result += Separator + "InstNum=" + InstNum; + if (!String.IsNullOrWhiteSpace(ClassNum)) result += Separator + "ClassNum=" + ClassNum; + if (!String.IsNullOrWhiteSpace(SpecFio)) result += Separator + "SpecFio=" + SpecFio; + if (!String.IsNullOrWhiteSpace(AddAmount)) result += Separator + "AddAmount=" + AddAmount; + if (!String.IsNullOrWhiteSpace(RuleId)) result += Separator + "RuleId=" + RuleId; + if (!String.IsNullOrWhiteSpace(ExecId)) result += Separator + "ExecId=" + ExecId; + if (!String.IsNullOrWhiteSpace(RegType)) result += Separator + "RegType=" + RegType; + if (!String.IsNullOrWhiteSpace(UIN)) result += Separator + "UIN=" + UIN; + if (!String.IsNullOrWhiteSpace(TechCode)) result += Separator + "TechCode=" + TechCode; + return result; + } + public override void Unpack(string data) + { + data = RetrieveServiceData(data); + string[] splitedString = data.Split(Separator); + foreach(string str in splitedString) + { + string[] splitedStr = str.Split(new string[] { "=" }, 2,StringSplitOptions.RemoveEmptyEntries); + switch (splitedStr[0]) + { + case "Name": + Name = splitedStr[1]; + break; + case "PersonalAcc": + PersonalAcc = splitedStr[1]; + break; + case "BankName": + BankName = splitedStr[1]; + break; + case "BIC": + BIC = splitedStr[1]; + break; + case "CorrespAcc": + CorrespAcc = splitedStr[1]; + break; + case "Sum": + Sum = splitedStr[1]; + break; + case "Purpose": + Purpose = splitedStr[1]; + break; + case "PayeeINN": + PayeeINNB = splitedStr[1]; + break; + case "PayerINN": + PayerINN = splitedStr[1]; + break; + case "DrawerStatus": + DrawerStatus = splitedStr[1]; + break; + case "KPP": + KPP = splitedStr[1]; + break; + case "CBC": + CBC = splitedStr[1]; + break; + case "OKTMO": + OKTMO = splitedStr[1]; + break; + case "PaytReason": + PaytReason = splitedStr[1]; + break; + case "TaxPeriod": + TaxPeriod = splitedStr[1]; + break; + case "DocNo": + DocNo = splitedStr[1]; + break; + case "DocDate": + DocDate = DateTime.Parse(splitedStr[1]); + break; + case "TaxPaytKind": + TaxPaytKind = splitedStr[1]; + break; + case "LastName": + LastName = splitedStr[1]; + break; + case "FirstName": + FirstName = splitedStr[1]; + break; + case "MiddleName": + MiddleName = splitedStr[1]; + break; + case "PayerAddress": + PayerAddress = splitedStr[1]; + break; + case "PersonalAccount": + PersonalAccount = splitedStr[1]; + break; + case "DocIdx": + DocIdx = splitedStr[1]; + break; + case "PensAcc": + PensAcc = splitedStr[1]; + break; + case "PersAcc": + PersAccp = splitedStr[1]; + break; + case "Contract": + Contract = splitedStr[1]; + break; + case "Flat": + Flat = splitedStr[1]; + break; + case "Phone": + Phone = splitedStr[1]; + break; + case "PayerIdType": + PayerIdType = splitedStr[1]; + break; + case "PayerIdNum": + PayerIdNum = splitedStr[1]; + break; + case "ChildFio": + ChildFio = splitedStr[1]; + break; + case "BirthDate": + BirthDate = DateTime.Parse(splitedStr[1]); + break; + case "PaymTerm": + PaymTerm = DateTime.Parse(splitedStr[1]); + break; + case "PaymPeriod": + PaymPeriod = splitedStr[1]; + break; + case "Category": + Category = splitedStr[1]; + break; + case "ServiceName": + ServiceName = splitedStr[1]; + break; + case "CounterId": + CounterId = splitedStr[1]; + break; + case "CounterVal": + CounterVal = splitedStr[1]; + break; + case "QuittId": + QuittId = splitedStr[1]; + break; + case "QuittDate": + QuittDate = DateTime.Parse(splitedStr[1]); + break; + case "InstNum": + InstNum = splitedStr[1]; + break; + case "ClassNum": + ClassNum = splitedStr[1]; + break; + case "SpecFio": + SpecFio = splitedStr[1]; + break; + case "AddAmount": + AddAmount = splitedStr[1]; + break; + case "RuleId": + RuleId = splitedStr[1]; + break; + case "ExecId": + ExecId = splitedStr[1]; + break; + case "RegType": + RegType = splitedStr[1]; + break; + case "UIN": + UIN = splitedStr[1]; + break; + case "TechCode": + TechCode = splitedStr[1]; + break; + } + } + + } + private string RetrieveServiceData(string data) + { + int firstSeparatorIndex = data.IndexOf(Separator); + + string retrievedData = data.Substring(0, firstSeparatorIndex); + data = data.Substring(firstSeparatorIndex + 1); + FormatIdentifier = retrievedData.Substring(0, 2); + VersionStandart = retrievedData.Substring(2, 4); + Encoding = retrievedData.Substring(6, 1); + + return data; + } + } class QRGeo : QRData { public string latitude; diff --git a/FastReport.Base/Code/AssemblyDescriptor.cs b/FastReport.Base/Code/AssemblyDescriptor.cs index 3e18f37d..108474a6 100644 --- a/FastReport.Base/Code/AssemblyDescriptor.cs +++ b/FastReport.Base/Code/AssemblyDescriptor.cs @@ -13,9 +13,7 @@ using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; -#if DOTNET_4 using System.Collections.Concurrent; -#endif using FastReport.Data; using FastReport.Engine; using FastReport.Utils; @@ -24,44 +22,25 @@ namespace FastReport.Code { internal partial class AssemblyDescriptor { -#if DOTNET_4 - private static ConcurrentDictionary FAssemblyCache; -#else - private static Dictionary FAssemblyCache; -#endif - private Assembly assembly; - private object instance; - private Report report; - private FastString scriptText; - private Hashtable expressions; - private List sourcePositions; + private static readonly ConcurrentDictionary FAssemblyCache; + private readonly FastString scriptText; + private readonly List sourcePositions; private int insertLine; private int insertPos; private bool needCompile; - private string shaKey = "FastReportCode"; - private static object compileLocker; + private const string shaKey = "FastReportCode"; + private readonly static object compileLocker; + private readonly string currentFolder; private const int RECOMPILE_COUNT = 1; - public Assembly Assembly - { - get { return assembly; } - } + public Assembly Assembly { get; private set; } - public object Instance - { - get { return instance; } - } + public object Instance { get; private set; } - public Report Report - { - get { return report; } - } + public Report Report { get; } - public Hashtable Expressions - { - get { return expressions; } - } + public Hashtable Expressions { get; } private void InsertItem(string text, string objName) { @@ -153,7 +132,7 @@ private string ReplaceDataItems(string expression) return args.Text.ToString(); } - private bool ContansAssembly(StringCollection assemblies, string assembly) + private bool ContansAssembly(IList assemblies, string assembly) { string asmName = Path.GetFileName(assembly); foreach (string a in assemblies) @@ -165,7 +144,7 @@ private bool ContansAssembly(StringCollection assemblies, string assembly) return false; } - private void AddFastReportAssemblies(StringCollection assemblies) + private void AddFastReportAssemblies(IList assemblies) { List list = new List(); RegisteredObjects.Objects.EnumItems(list); @@ -183,17 +162,36 @@ private void AddFastReportAssemblies(StringCollection assemblies) } } - private void AddReferencedAssemblies(StringCollection assemblies, string defaultPath) + private void AddReferencedAssemblies(IList assemblies, string defaultPath) { - string location; foreach (string s in Report.ReferencedAssemblies) { - location = GetFullAssemblyReference(s, defaultPath); - if (location != "" && !ContansAssembly(assemblies, location)) - assemblies.Add(location); +#if NETSTANDARD + // replace + if (s == "System.Windows.Forms.dll") + { + AddReferencedAssembly(assemblies, defaultPath, "FastReport.Compat"); + continue; + } +#endif + // fix for old reports with "System.Windows.Forms.DataVisualization" in referenced assemblies + if (s.IndexOf("System.Windows.Forms.DataVisualization") != -1) + { + AddReferencedAssembly(assemblies, defaultPath, "FastReport.DataVisualization"); + continue; + } + + AddReferencedAssembly(assemblies, defaultPath, s); } } + private void AddReferencedAssembly(IList assemblies, string defaultPath, string assemblyName) + { + string location = GetFullAssemblyReference(assemblyName, defaultPath); + if (location != "" && !ContansAssembly(assemblies, location)) + assemblies.Add(location); + } + private string GetFullAssemblyReference(string relativeReference, string defaultPath) { if (relativeReference == null || relativeReference.Trim() == "") @@ -239,7 +237,7 @@ private string GetFullAssemblyReference(string relativeReference, string default private void AddExpression(string expression, Base source, bool forceSimpleItems) { - if (expression.Trim() == "" || expressions.ContainsKey(expression)) + if (expression.Trim() == "" || Expressions.ContainsKey(expression)) return; string expr = expression; @@ -257,7 +255,7 @@ private void AddExpression(string expression, Base source, bool forceSimpleItems // handle complex expressions, relations ExpressionDescriptor descriptor = new ExpressionDescriptor(this); - expressions.Add(expression, descriptor); + Expressions.Add(expression, descriptor); descriptor.MethodName = "CalcExpression"; if (DataHelper.IsValidColumn(Report.Dictionary, expr)) @@ -369,23 +367,7 @@ public void Compile() } private void InternalCompile() - { - // set the current folder - string currentFolder = Config.ApplicationFolder; - if (Config.WebMode) - { - try - { - if (Directory.Exists(currentFolder + @"Bin\")) - currentFolder += @"Bin\"; - } - catch - { - } - } - // Commented by Samuray - //Directory.SetCurrentDirectory(currentFolder); - + { // configure compiler options CompilerParameters cp = new CompilerParameters(); AddFastReportAssemblies(cp.ReferencedAssemblies); @@ -439,8 +421,8 @@ private bool InternalCompile(CompilerParameters cp, out CompilerResults cr) Assembly cachedAssembly = null; if (FAssemblyCache.TryGetValue(assemblyHash, out cachedAssembly)) { - assembly = cachedAssembly; - InitInstance(assembly.CreateInstance("FastReport.ReportScript")); + Assembly = cachedAssembly; + InitInstance(Assembly.CreateInstance("FastReport.ReportScript")); cr = null; return true; } @@ -452,19 +434,16 @@ private bool InternalCompile(CompilerParameters cp, out CompilerResults cr) Config.OnScriptCompile(ssea); cr = provider.CompileAssemblyFromSource(cp, scriptText.ToString()); - assembly = null; - instance = null; + Assembly = null; + Instance = null; if (cr.Errors.Count != 0) // Compile errors return false; -#if DOTNET_4 FAssemblyCache.TryAdd(assemblyHash, cr.CompiledAssembly); -#else - FAssemblyCache.Add(assemblyHash, cr.CompiledAssembly); -#endif - assembly = cr.CompiledAssembly; - InitInstance(assembly.CreateInstance("FastReport.ReportScript")); + + Assembly = cr.CompiledAssembly; + InitInstance(Assembly.CreateInstance("FastReport.ReportScript")); return true; } } @@ -476,7 +455,7 @@ private bool InternalCompile(CompilerParameters cp, out CompilerResults cr) private bool HandleCompileErrors(CompilerParameters cp, CompilerResults cr, out string errors) { errors = string.Empty; - List assemblyList = new List(4); + List additionalAssemblies = new List(4); Regex regex; if (Config.WebMode && Config.EnableScriptSecurity) @@ -536,11 +515,17 @@ private bool HandleCompileErrors(CompilerParameters cp, CompilerResults cr, out // try to add reference try { - const string pattern = @"'(\S{1,}),"; + // in .Net Core compiler will return other quotes +#if NETSTANDARD || NETCOREAPP + const string quotes = "\'"; +#else + const string quotes = "\""; +#endif + const string pattern = quotes + @"(\S{1,}),"; regex = new Regex(pattern, RegexOptions.Compiled); - string assemblyName = regex.Match(ce.ErrorText).Groups[1].Value; // Groups[1] include string without ' and , symbols - if (!assemblyList.Contains(assemblyName)) - assemblyList.Add(assemblyName); + string assemblyName = regex.Match(ce.ErrorText).Groups[1].Value; // Groups[1] include string without quotes and , symbols + if (!additionalAssemblies.Contains(assemblyName)) + additionalAssemblies.Add(assemblyName); continue; } catch { } @@ -575,8 +560,8 @@ private bool HandleCompileErrors(CompilerParameters cp, CompilerResults cr, out } } - if(assemblyList.Count > 0) // need recompile - return ReCompile(cp, cr, assemblyList); + if(additionalAssemblies.Count > 0) // need recompile + return ReCompile(cp, cr, additionalAssemblies); return false; } @@ -584,30 +569,31 @@ private bool HandleCompileErrors(CompilerParameters cp, CompilerResults cr, out /// /// Returns true, if recompilation is successful /// - private bool ReCompile(CompilerParameters cp, CompilerResults cr, List assemblyList) + private bool ReCompile(CompilerParameters cp, CompilerResults cr, IList additionalAssemblies) { // try to load missing assemblies - foreach (string assemblyName in assemblyList) + foreach (string assemblyName in additionalAssemblies) { - cp.ReferencedAssemblies.Add(assemblyName); + AddReferencedAssembly(cp.ReferencedAssemblies, currentFolder, assemblyName); } + return InternalCompile(cp, out cr); } public void InitInstance(object instance) { - this.instance = instance; + this.Instance = instance; InitFields(); } public bool ContainsExpression(string expr) { - return expressions.ContainsKey(expr); + return Expressions.ContainsKey(expr); } public object CalcExpression(string expr, Variant value) { - FastReport.Code.ExpressionDescriptor expressionDescriptor = expressions[expr] as FastReport.Code.ExpressionDescriptor; + FastReport.Code.ExpressionDescriptor expressionDescriptor = Expressions[expr] as FastReport.Code.ExpressionDescriptor; if (expressionDescriptor != null) return expressionDescriptor.Invoke(new object[] { expr, value }); else @@ -623,12 +609,12 @@ public void InvokeEvent(string name, object[] parms) if (!ContainsExpression(exprName)) { ExpressionDescriptor descriptor = new ExpressionDescriptor(this); - expressions.Add(exprName, descriptor); + Expressions.Add(exprName, descriptor); descriptor.MethodName = name; } try { - (expressions[exprName] as ExpressionDescriptor).Invoke(parms); + (Expressions[exprName] as ExpressionDescriptor).Invoke(parms); } catch (TargetInvocationException ex) { @@ -638,9 +624,9 @@ public void InvokeEvent(string name, object[] parms) public AssemblyDescriptor(Report report, string scriptText) { - this.report = report; + this.Report = report; this.scriptText = new FastString(scriptText); - expressions = new Hashtable(); + Expressions = new Hashtable(); sourcePositions = new List(); insertPos = Report.CodeHelper.GetPositionToInsertOwnItems(scriptText); if (insertPos == -1) @@ -656,15 +642,29 @@ public AssemblyDescriptor(Report report, string scriptText) if (scriptText != Report.CodeHelper.EmptyScript()) needCompile = true; } + + // set the current folder + currentFolder = Config.ApplicationFolder; + if (Config.WebMode) + { + try + { + string bin_directory = Path.Combine(currentFolder, "Bin"); + if (Directory.Exists(bin_directory)) + currentFolder = bin_directory; + } + catch + { + } + } + // Commented by Samuray + //Directory.SetCurrentDirectory(currentFolder); } static AssemblyDescriptor() { -#if DOTNET_4 FAssemblyCache = new ConcurrentDictionary(); -#else - FAssemblyCache = new Dictionary(); -#endif + compileLocker = new object(); } diff --git a/FastReport.Base/ComponentBase.cs b/FastReport.Base/ComponentBase.cs index 4f3c4a9f..a64279b6 100644 --- a/FastReport.Base/ComponentBase.cs +++ b/FastReport.Base/ComponentBase.cs @@ -509,7 +509,21 @@ public override string[] GetExpressions() { if (VisibleExpression.StartsWith("[") && VisibleExpression.EndsWith("]")) { - expressions.Add(VisibleExpression.Substring(1, VisibleExpression.Length - 2)); + string tempExpression = VisibleExpression.Substring(1, VisibleExpression.Length - 2); + int firstOpen = tempExpression.IndexOf("["); + int firstClose = tempExpression.IndexOf("]"); + int lastOpen = tempExpression.LastIndexOf("["); + int lastClose = tempExpression.LastIndexOf("]"); + if ((firstOpen < 0 && firstClose >= 0) || (lastOpen >= 0 && lastClose < 0) + || (firstOpen >= 0 && firstClose >= 0 && firstClose < firstOpen) + || (lastOpen >= 0 && lastClose >= 0 && lastOpen > lastClose)) + { + expressions.Add(VisibleExpression); + } + else + { + expressions.Add(tempExpression); + } } else { @@ -521,7 +535,21 @@ public override string[] GetExpressions() { if (PrintableExpression.StartsWith("[") && PrintableExpression.EndsWith("]")) { - expressions.Add(PrintableExpression.Substring(1, PrintableExpression.Length - 2)); + string tempExpression = PrintableExpression.Substring(1, PrintableExpression.Length - 2); + int firstOpen = tempExpression.IndexOf("["); + int firstClose = tempExpression.IndexOf("]"); + int lastOpen = tempExpression.LastIndexOf("["); + int lastClose = tempExpression.LastIndexOf("]"); + if ((firstOpen < 0 && firstClose >= 0) || (lastOpen >= 0 && lastClose < 0) + || (firstOpen >= 0 && firstClose >= 0 && firstClose < firstOpen) + || (lastOpen >= 0 && lastClose >= 0 && lastOpen > lastClose)) + { + expressions.Add(PrintableExpression); + } + else + { + expressions.Add(tempExpression); + } } else { diff --git a/FastReport.Base/Engine/ReportEngine.Bands.cs b/FastReport.Base/Engine/ReportEngine.Bands.cs index b8feef34..3cb058e3 100644 --- a/FastReport.Base/Engine/ReportEngine.Bands.cs +++ b/FastReport.Base/Engine/ReportEngine.Bands.cs @@ -211,7 +211,21 @@ internal bool CanPrint(ReportComponentBase obj) object expression = null; if (obj.VisibleExpression.StartsWith("[") && obj.VisibleExpression.EndsWith("]")) { - expression = Report.Calc(obj.VisibleExpression.Substring(1, obj.VisibleExpression.Length - 2)); + string tempExpression = obj.VisibleExpression.Substring(1, obj.VisibleExpression.Length - 2); + int firstOpen = tempExpression.IndexOf("["); + int firstClose = tempExpression.IndexOf("]"); + int lastOpen = tempExpression.LastIndexOf("["); + int lastClose = tempExpression.LastIndexOf("]"); + if ((firstOpen < 0 && firstClose >= 0) || (lastOpen >= 0 && lastClose < 0) + || (firstOpen >= 0 && firstClose >= 0 && firstClose < firstOpen) + || (lastOpen >= 0 && lastClose >= 0 && lastOpen > lastClose)) + { + expression = Report.Calc(obj.VisibleExpression); + } + else + { + expression = Report.Calc(tempExpression); + } } else { @@ -229,7 +243,21 @@ internal bool CanPrint(ReportComponentBase obj) object expression = null; if (obj.ExportableExpression.StartsWith("[") && obj.ExportableExpression.EndsWith("]")) { - expression = Report.Calc(obj.ExportableExpression.Substring(1, obj.ExportableExpression.Length - 2)); + string tempExpression = obj.ExportableExpression.Substring(1, obj.ExportableExpression.Length - 2); + int firstOpen = tempExpression.IndexOf("["); + int firstClose = tempExpression.IndexOf("]"); + int lastOpen = tempExpression.LastIndexOf("["); + int lastClose = tempExpression.LastIndexOf("]"); + if ((firstOpen < 0 && firstClose >= 0) || (lastOpen >= 0 && lastClose < 0) + || (firstOpen >= 0 && firstClose >= 0 && firstClose < firstOpen) + || (lastOpen >= 0 && lastClose >= 0 && lastOpen > lastClose)) + { + expression = Report.Calc(obj.ExportableExpression); + } + else + { + expression = Report.Calc(tempExpression); + } } else { @@ -247,7 +275,21 @@ internal bool CanPrint(ReportComponentBase obj) object expression = null; if (obj.PrintableExpression.StartsWith("[") && obj.PrintableExpression.EndsWith("]")) { - expression = Report.Calc(obj.PrintableExpression.Substring(1, obj.PrintableExpression.Length - 2)); + string tempExpression = obj.PrintableExpression.Substring(1, obj.PrintableExpression.Length - 2); + int firstOpen = tempExpression.IndexOf("["); + int firstClose = tempExpression.IndexOf("]"); + int lastOpen = tempExpression.LastIndexOf("["); + int lastClose = tempExpression.LastIndexOf("]"); + if ((firstOpen < 0 && firstClose >= 0) || (lastOpen >= 0 && lastClose < 0) + || (firstOpen >= 0 && firstClose >= 0 && firstClose < firstOpen) + || (lastOpen >= 0 && lastClose >= 0 && lastOpen > lastClose)) + { + expression = Report.Calc(obj.PrintableExpression); + } + else + { + expression = Report.Calc(tempExpression); + } } else { diff --git a/FastReport.Base/Engine/ReportEngine.Pages.cs b/FastReport.Base/Engine/ReportEngine.Pages.cs index d6170209..41f9f3ca 100644 --- a/FastReport.Base/Engine/ReportEngine.Pages.cs +++ b/FastReport.Base/Engine/ReportEngine.Pages.cs @@ -67,7 +67,7 @@ private void RunReportPage(ReportPage page) private void RunReportPages() { #if TIMETRIAL - if (new DateTime($YEAR, $MONTH, $DAY) < DateTime.Now) + if (new DateTime($YEAR, $MONTH, $DAY) < SystemFake.DateTime.Now) throw new Exception("The trial version is now expired!"); #endif @@ -363,6 +363,8 @@ internal void EndPage(bool startPage) OnStateChanged(page, EngineState.PageFinished); ShowPageFooter(startPage); + if (pagesLimit > 0 && PreparedPages.Count >= pagesLimit) + Report.Abort(); if (Report.MaxPages > 0 && PreparedPages.Count >= Report.MaxPages) Report.Abort(); if (startPage) diff --git a/FastReport.Base/Engine/ReportEngine.cs b/FastReport.Base/Engine/ReportEngine.cs index f4668663..3efd6c38 100644 --- a/FastReport.Base/Engine/ReportEngine.cs +++ b/FastReport.Base/Engine/ReportEngine.cs @@ -26,6 +26,7 @@ public partial class ReportEngine private bool finalPass; private int firstReportPage; private bool isFirstReportPage; + private int pagesLimit = 0; #endregion Fields @@ -414,9 +415,15 @@ internal bool Run(bool runDialogs, bool append, bool resetDataState) return Run(runDialogs, append, resetDataState, null); } + internal bool Run(bool runDialogs, bool append, bool resetDataState, int pagesLimit) + { + this.pagesLimit = pagesLimit; + return Run(runDialogs, append, resetDataState, null); + } + internal bool Run(bool runDialogs, bool append, bool resetDataState, ReportPage page) { - date = DateTime.Now; + date = SystemFake.DateTime.Now; Report.SetOperation(ReportOperation.Running); ResetDesigningFlag(); @@ -457,13 +464,22 @@ internal bool Run(bool runDialogs, bool append, bool resetDataState, ReportPage PreparedPages.RemovePage(PreparedPages.Count - 1); } } + + // Limit the prepared pages again because pagesLimit has better priority than Report.MaxPages. + if (pagesLimit > 0) + { + while (PreparedPages.Count > pagesLimit) + { + PreparedPages.RemovePage(PreparedPages.Count - 1); + } + } } return true; } internal void RunPhase1() { - date = DateTime.Now; + date = SystemFake.DateTime.Now; Report.SetOperation(ReportOperation.Running); ResetDesigningFlag(); InitializeData(); @@ -500,6 +516,15 @@ internal void RunPhase2() PreparedPages.RemovePage(PreparedPages.Count - 1); } } + + // Limit the prepared pages again because pagesLimit has better priority than Report.MaxPages. + if (pagesLimit > 0) + { + while (PreparedPages.Count > pagesLimit) + { + PreparedPages.RemovePage(PreparedPages.Count - 1); + } + } } } diff --git a/FastReport.Base/Export/ExportUtils.cs b/FastReport.Base/Export/ExportUtils.cs index de379e99..5ba7365c 100644 --- a/FastReport.Base/Export/ExportUtils.cs +++ b/FastReport.Base/Export/ExportUtils.cs @@ -266,7 +266,9 @@ internal static FastString HtmlString(string text, TextRenderType textRenderType else if (crlf == CRLF.odt) Result.Append(""); else - Result.Append("
"); + { + Result.Append("

"); + } i++; } else if (text[i] == '\t' && crlf == CRLF.odt) @@ -534,7 +536,7 @@ internal static FastString StrToHex2(string s) internal static string GetID() { - return Guid.NewGuid().ToString(); + return SystemFake.Guid.NewGuid().ToString(); } internal static void CopyStream(Stream source, Stream target) diff --git a/FastReport.Base/Export/Html/HTMLExportUtils.cs b/FastReport.Base/Export/Html/HTMLExportUtils.cs index 95ef03ca..06b1aefb 100644 --- a/FastReport.Base/Export/Html/HTMLExportUtils.cs +++ b/FastReport.Base/Export/Html/HTMLExportUtils.cs @@ -120,7 +120,7 @@ private void WriteMHTHeader(Stream Stream, string FileName) string s = "=?utf-8?B?" + System.Convert.ToBase64String(Encoding.UTF8.GetBytes(FileName)) + "?="; sb.Append("From: ").AppendLine(s); sb.Append("Subject: ").AppendLine(s); - sb.Append("Date: ").AppendLine(ExportUtils.GetRFCDate(DateTime.Now)); + sb.Append("Date: ").AppendLine(ExportUtils.GetRFCDate(SystemFake.DateTime.Now)); sb.AppendLine("MIME-Version: 1.0"); sb.Append("Content-Type: multipart/related; type=\"text/html\"; boundary=\"").Append(boundary).AppendLine("\""); sb.AppendLine(); diff --git a/FastReport.Base/Fakes.cs b/FastReport.Base/Fakes.cs new file mode 100644 index 00000000..101b80c2 --- /dev/null +++ b/FastReport.Base/Fakes.cs @@ -0,0 +1,58 @@ +//#define USE_FAKES + +// This file represent mock for System.DateTime & System.Guid (because Microsoft Fakes doesn't correct work in .Net Core) + +using System.Runtime.CompilerServices; + +namespace SystemFake +{ + internal struct DateTime + { + internal static System.DateTime Now + { +#if NETSTANDARD || NETCOREAPP + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + get + { +#if !USE_FAKES + return System.DateTime.Now; +#else + return new System.DateTime(0, System.DateTimeKind.Utc); +#endif + } + } + + + internal static System.DateTime UtcNow + { +#if NETSTANDARD || NETCOREAPP + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + get + { +#if !USE_FAKES + return System.DateTime.UtcNow; +#else + return new System.DateTime(0, System.DateTimeKind.Utc); +#endif + } + } + } + + + internal struct Guid + { +#if NETSTANDARD || NETCOREAPP + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + internal static System.Guid NewGuid() + { +#if !USE_FAKES + return System.Guid.NewGuid(); +#else + return System.Guid.Empty; +#endif + } + } +} diff --git a/FastReport.Base/Functions/NumToLettersBase.cs b/FastReport.Base/Functions/NumToLettersBase.cs new file mode 100644 index 00000000..b4969b2b --- /dev/null +++ b/FastReport.Base/Functions/NumToLettersBase.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace FastReport.Functions +{ + internal abstract class NumToLettersBase + { + #region Protected Methods + protected string Str(int value, char[] letters) + { + if (value < 0) return ""; + + int n = value; + StringBuilder r = new StringBuilder(); + + //if (minus) + // r.Insert(0, GetMinus() + " "); + int letter; + while (n >= letters.Length) + { + letter = n % letters.Length; + r.Insert(0, letters[letter]); + n /= letters.Length; + if (n < letters.Length) --n; + } + r.Insert(0, letters[n]); + + return r.ToString(); + } + #endregion + + #region Public Methods + public abstract string ConvertNumber(int value, bool isUpper); + #endregion + } +} diff --git a/FastReport.Base/Functions/NumToLettersEn.cs b/FastReport.Base/Functions/NumToLettersEn.cs new file mode 100644 index 00000000..34309342 --- /dev/null +++ b/FastReport.Base/Functions/NumToLettersEn.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace FastReport.Functions +{ + internal class NumToLettersEn : NumToLettersBase + { + #region Private Fields + private static char[] letters = + { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' + }; + + private static char[] upperLetters = + { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' + }; + #endregion + + #region Public Methods + public override string ConvertNumber(int value, bool isUpper) + { + return Str(value, (isUpper) ? (upperLetters) : (letters)); + } + #endregion + } +} diff --git a/FastReport.Base/Functions/NumToLettersRu.cs b/FastReport.Base/Functions/NumToLettersRu.cs new file mode 100644 index 00000000..ec04bc6e --- /dev/null +++ b/FastReport.Base/Functions/NumToLettersRu.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace FastReport.Functions +{ + internal class NumToLettersRu : NumToLettersBase + { + #region Private Fields + private static char[] letters = + { + 'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', + 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я' + }; + + private static char[] upperLetters = + { + 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', + 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я' + }; + #endregion + + #region Public Methods + public override string ConvertNumber(int value, bool isUpper) + { + return Str(value, (isUpper) ? (upperLetters) : (letters)); + } + #endregion + } +} diff --git a/FastReport.Base/Functions/NumToWordSp.cs b/FastReport.Base/Functions/NumToWordSp.cs new file mode 100644 index 00000000..efed6c37 --- /dev/null +++ b/FastReport.Base/Functions/NumToWordSp.cs @@ -0,0 +1,184 @@ +using System; +using System.Text; +using System.Collections; +using System.Collections.Generic; + +namespace FastReport.Functions +{ + + internal class NumToWordsSp : NumToWordsBase + { + + private static Dictionary currencyList; + + private static WordInfo thousands = new WordInfo("mil"); + private static WordInfo millions = new WordInfo("millón", "millones"); + private static WordInfo milliards = new WordInfo("millardo", "millardos"); + private static WordInfo trillions = new WordInfo("billón", "billiones"); + + //if million, milliard or trillions use un instead of uno. + private bool _useUn; + + private static string[] hunds = { + "","cien","doscientos","trescientos","cuatrocientos","quinientos","seiscientos","setecientos","ochocientos","novecientos" + }; + + private static string[] tens = + { + "", "diez", "veinte", "treinta", "cuarenta", "cincuenta", "sesenta", "setenta", "ochenta", "noventa" + }; + + private static string[] fixedWords = + { + "","uno","dos","tres","cuatro","cinco","seis","siete","ocho","nueve","diez","once","doce","trece","catorce","quince","dieciséis", + "diecisiete","dieciocho","diecinueve" + }; + + private static string[] fixedWords21To29 = + { + "veintiuno","veintidós","veintitrés","veinticuatro","veinticinco","veintiséis","veintisiete","veintiocho","veintinueve" + }; + + protected override CurrencyInfo GetCurrency(string currencyName) + { + currencyName = currencyName.ToUpper(); + return currencyList[currencyName]; + } + + protected override string GetFixedWords(bool male, long value) + { + if (_useUn && value == 1) return "un"; + return fixedWords[value]; + } + + + + protected override string GetHund(bool male, long value) + { + return hunds[value / 100]; + } + + + protected override WordInfo GetMilliards() + { + return milliards; + } + + protected override WordInfo GetMillions() + { + return millions; + } + + protected override string GetMinus() + { + return "menos"; + } + + protected override string GetTen(bool male, long value) + { + return tens[value]; + } + + + protected override WordInfo GetThousands() + { + return thousands; + } + + protected override WordInfo GetTrillions() + { + return trillions; + } + + protected override string GetZero() + { + return "cero"; + } + + protected override string Str1000(long value, WordInfo info, int counter) + { + long val = value % 1000; + if (val == 0) + return ""; + + StringBuilder r = new StringBuilder(); + // add hundred + string hund = GetHund(info.male, val); + if (hund != "") + r.Append(hund); + + // decide whether to use the 100-10 separator or not + string sep100_10 = Get100_10Separator(); + if (value < 1000 && hund == "") + sep100_10 = ""; + + val = val % 100; + if (counter == 3 || counter==4 || counter==5) _useUn = true; + else _useUn = false; + if (val > 20 && val < 30) + { + r.Append(sep100_10 + fixedWords21To29[val - 21]); + } + + else if (val < GetFixedWordsCount()) + { + // val is less than fixed words count (usually 20), get fixed words + string frac20 = GetFixedWords(info.male, val); + if (frac20 != "") + r.Append(sep100_10 + frac20); + } + else + { + // val is greater than fixed words count (usually 20), get tens separately + string ten = GetTen(info.male, val / 10); + string frac10 = GetFixedWords(info.male, val % 10); + + // decide whether to use 10-1 separator or not + if (ten != "" && frac10 != "") + r.Append(sep100_10 + ten + Get10_1Separator() + frac10); + else if (ten != "") + r.Append(sep100_10 + ten); + else if (frac10 != "") + r.Append(sep100_10 + frac10); + } + + // add currency/group word + r.Append(" "); + r.Append(Case(value, info)); + + // make the result starting with letter and ending with space + if (r.Length != 0) + r.Append(" "); + return r.ToString().TrimStart(new char[] { ' ' }); + } + + protected override string Get10_1Separator() + { + return " y "; + } + + protected override string Get100_10Separator() + { + return " "; + } + + protected override string GetDecimalSeparator() + { + return "y "; + } + + + static NumToWordsSp() + { + currencyList = new Dictionary(2); + currencyList.Add("EUR", new CurrencyInfo( + new WordInfo ("euro", "euros"), + new WordInfo( "céntimo", "céntimos"))); + + currencyList.Add("USD",new CurrencyInfo( + new WordInfo("dólar", "dólares"), + new WordInfo("céntimo", "céntimos"))); + + } + } +} diff --git a/FastReport.Base/Functions/NumToWordsBase.cs b/FastReport.Base/Functions/NumToWordsBase.cs index bfe5fcc2..6ab96009 100644 --- a/FastReport.Base/Functions/NumToWordsBase.cs +++ b/FastReport.Base/Functions/NumToWordsBase.cs @@ -1,5 +1,6 @@ // Based on RSDN RusCurrency class using System; +using System.Collections.Generic; using System.Text; namespace FastReport.Functions @@ -166,9 +167,18 @@ public string ConvertCurrency(decimal value, string currencyName) CurrencyInfo currency = GetCurrency(currencyName); return Str(value, currency.senior, currency.junior); } - catch + catch (KeyNotFoundException e) { - throw new Exception("Currency \"" + currencyName + "\" is not defined in the \"" + GetType().Name + "\" converter."); + throw new Exception("Currency \"" + currencyName + "\" is not defined in the \"" + GetType().Name + + "\" converter."); + } + catch (NotImplementedException e) + { + throw new Exception("Method " + e.TargetSite.ToString() + " wasn't implemented"); + } + catch (Exception e) + { + throw new Exception("There is an exception - "+e.ToString()); } } diff --git a/FastReport.Base/Functions/NumToWordsIn.cs b/FastReport.Base/Functions/NumToWordsIn.cs new file mode 100644 index 00000000..99703b26 --- /dev/null +++ b/FastReport.Base/Functions/NumToWordsIn.cs @@ -0,0 +1,228 @@ +using System.Text; +using System.Collections.Generic; + +namespace FastReport.Functions +{ + internal class NumToWordsIn : NumToWordsBase + { + private bool shouldReturnMany = false; //if third or fourth counter, so use lakh/crore instead of thousands/millions + private static Dictionary currencyList; + + private static string[] fixedWords = + { + "", "one", "two", "three", "four", "five", "six", "seven", + "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", + "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" + }; + + private static string[] tens = + { + "", "ten", "twenty", "thirty", + "forty", "fifty", "sixty", "seventy", + "eighty", "ninety" + }; + + private static string[] hunds = + { + "", "one hundred", "two hundred", "three hundred", "four hundred", + "five hundred", "six hundred", "seven hundred", "eight hundred", "nine hundred" + }; + + + private static WordInfo thousands = new WordInfo("thousand", "crore"); + private static WordInfo millions = new WordInfo("million", "lakh"); + private static WordInfo milliards = new WordInfo("billion", "crore"); + private static WordInfo trillions = new WordInfo("trillion"); + + protected override CurrencyInfo GetCurrency(string currencyName) + { + currencyName = currencyName.ToUpper(); + return currencyList[currencyName]; + } + + protected override string GetFixedWords(bool male, long value) + { + return fixedWords[value]; + } + + + + + protected override string GetHund(bool male, long value) + { + return hunds[value / 100]; + } + + protected override WordInfo GetMilliards() + { + return milliards; + } + + protected override WordInfo GetMillions() + { + return millions; + } + + protected override string GetMinus() + { + return "minus"; + } + + protected override string GetTen(bool male, long value) + { + return tens[value]; + } + + protected override WordInfo GetThousands() + { + return thousands; + } + + protected override WordInfo GetTrillions() + { + return trillions; + } + + protected override string GetZero() + { + return "zero"; + } + + protected override string GetDecimalSeparator() + { + return "and "; + } + + protected override string Get10_1Separator() + { + return "-"; + } + + protected override void Str(long value, WordInfo senior, StringBuilder result) + { + if (value == 0) + result.Append(GetZero() + " " + senior.many + " "); + else + { + if (value % 1000 != 0) + result.Append(Str1000(value, senior, 1)); + else + result.Append(" " + senior.many + " "); + value /= 1000; + //grouping digits not by threes as in international system, but by sets of two digits + result.Insert(0, Str1000(value, GetThousands(), 2)); + value /= 100; + result.Insert(0, Str1000(value, GetMillions(), 3)); + value /= 100; + result.Insert(0, Str1000(value, GetMilliards(), 4)); + value /= 100; + result.Insert(0, Str1000(value, new WordInfo("arab"), 5)); + value /= 100; + result.Insert(0, Str1000(value, new WordInfo("kharab"), 6)); + value /= 100; + result.Insert(0, Str1000(value, new WordInfo("nil"), 7)); + result.Replace(" ", " "); + + } + } + + + protected override string Case(long value, WordInfo info) + { + if (shouldReturnMany == true) + { + return info.many; + } + return info.one; + + /*if (value % 100 == 1) + return info.one; + return info.many;*/ + } + + protected override string Str1000(long value, WordInfo info, int counter) + { + long val; + + //if its third or + if (counter == 3 || counter == 4) shouldReturnMany = true; + else shouldReturnMany = false; + + if (counter == 1) val = value % 1000; + else val = value % 100; + + if (val == 0) + return ""; + + StringBuilder r = new StringBuilder(); + + // add hundred + + string hund = GetHund(info.male, val); + + if (hund != "") + r.Append(hund); + + + // decide whether to use the 100-10 separator or not + string sep100_10 = Get100_10Separator(); + if (value < 1000 && hund == "") + sep100_10 = ""; + + val = val % 100; + if (val < GetFixedWordsCount()) + { + // val is less than fixed words count (usually 20), get fixed words + string frac20 = GetFixedWords(info.male, val); + if (frac20 != "") + r.Append(sep100_10 + frac20); + } + else + { + // val is greater than fixed words count (usually 20), get tens separately + string ten = GetTen(info.male, val / 10); + string frac10 = GetFixedWords(info.male, val % 10); + + // decide whether to use 10-1 separator or not + if (ten != "" && frac10 != "") + r.Append(sep100_10 + ten + Get10_1Separator() + frac10); + else if (ten != "") + r.Append(sep100_10 + ten); + else if (frac10 != "") + r.Append(sep100_10 + frac10); + } + //Twenty-Four crore and seventy-Five lakh and Eighty-Zero thousand rupees and 00 paise + // add currency/group word + r.Append(" "); + if (counter == 1 && value % 100 != 1) + { + shouldReturnMany = true; + } + r.Append(Case(value, info)); + + // make the result starting with letter and ending with space + if (r.Length != 0) + r.Append(" "); + return r.ToString().TrimStart(new char[] { ' ' }); + + + } + + + static NumToWordsIn() + { + currencyList = new Dictionary(); + currencyList.Add("USD", new CurrencyInfo( + new WordInfo("dollar", "dollars"), + new WordInfo("cent", "cents"))); + currencyList.Add("EUR", new CurrencyInfo( + new WordInfo("euro", "euros"), + new WordInfo("cent", "cents"))); + currencyList.Add("INR", new CurrencyInfo( + new WordInfo("rupee", "rupees"), + new WordInfo("paise") + )); + + } + } +} diff --git a/FastReport.Base/Functions/NumToWordsPersian.cs b/FastReport.Base/Functions/NumToWordsPersian.cs new file mode 100644 index 00000000..5ec185ec --- /dev/null +++ b/FastReport.Base/Functions/NumToWordsPersian.cs @@ -0,0 +1,115 @@ +using System; +using System.Text; +using System.Collections; +using System.Collections.Generic; + +namespace FastReport.Functions +{ + internal class NumToWordsPersian : NumToWordsBase + { + private static Dictionary currencyList; + + private static string[] fixedWords = + { + "", "یک", "دو", "سه", "چهار", "پنج", "شش", + "هفت", "هشت", "نه", "ده", "یازده", + "دوازده", "سیزده", "چهارده", "پانزده", + "شانزده", "هفده", "هجده", "نوزده" + }; + + private static string[] tens = + { + "", "ده", "بیست", "سی", "چهل", "پنجاه", + "شصت", "هفتاد", "هشتاد", "نود" + }; + + private static string[] hunds = + { + "", "صد", "دویست", "سیصد", "چهارصد", + "پانصد", "ششصد", "هفتصد", "هشتصد", "نهصد" + }; + + private static WordInfo thousands = new WordInfo( "هزار"); + private static WordInfo millions = new WordInfo("میلیون"); + private static WordInfo milliards = new WordInfo("میلیارد"); + private static WordInfo trillions = new WordInfo("تریلیون"); + + protected override string GetFixedWords(bool male, long value) + { + string result = fixedWords[value]; + return result; + } + + protected override string GetTen(bool male, long value) + { + return tens[value]; + } + + protected override string GetHund(bool male, long value) + { + return hunds[value / 100]; + } + + protected override WordInfo GetThousands() + { + return thousands; + } + + protected override WordInfo GetMillions() + { + return millions; + } + + protected override WordInfo GetMilliards() + { + return milliards; + } + + protected override WordInfo GetTrillions() + { + return trillions; + } + + protected override CurrencyInfo GetCurrency(string currencyName) + { + return currencyList[currencyName]; + } + + protected override string GetZero() + { + return "صفر"; + } + + protected override string GetMinus() + { + return "منفی"; + } + + protected override string Get10_1Separator() + { + return " و "; + } + + protected override string Get100_10Separator() + { + return " و "; + } + + protected override string GetDecimalSeparator() + { + return "و "; + } + static NumToWordsPersian() + { + currencyList = new Dictionary(3); + currencyList.Add("EUR", new CurrencyInfo( + new WordInfo("یورو"), + new WordInfo("یورو سنت"))); + currencyList.Add("USD", new CurrencyInfo( + new WordInfo("دلار"), + new WordInfo("سنت"))); + currencyList.Add("IRR", new CurrencyInfo( + new WordInfo("ریال‎"), new WordInfo("دینار"))); + } + } +} diff --git a/FastReport.Base/Functions/NumToWordsRu.cs b/FastReport.Base/Functions/NumToWordsRu.cs index 91a1657b..60629a41 100644 --- a/FastReport.Base/Functions/NumToWordsRu.cs +++ b/FastReport.Base/Functions/NumToWordsRu.cs @@ -138,6 +138,6 @@ static NumToWordsRu() currencyList.Add("BBYN", new CurrencyInfo( new WordInfo(true, "белорусский рубль", "белорусских рубля", "белорусских рублей"), new WordInfo(false, "белорусская копейка", "белорусских копейки", "белорусских копеек"))); - } + } } } \ No newline at end of file diff --git a/FastReport.Base/Functions/NumToWordsUkr.cs b/FastReport.Base/Functions/NumToWordsUkr.cs new file mode 100644 index 00000000..7e8eb3c2 --- /dev/null +++ b/FastReport.Base/Functions/NumToWordsUkr.cs @@ -0,0 +1,136 @@ +using System; +using System.Text; +using System.Collections; +using System.Collections.Generic; + +namespace FastReport.Functions +{ + internal class NumToWordsUkr : NumToWordsBase + { + private static Dictionary currencyList; + + private static string[] fixedWords = + { + "", "один", "два", "три", "чотири", "п’ять", "шість", + "сім", "вісім", "дев’ять", "десять", "одинадцять", + "дванадцять", "тринадцять", "чотирнадцять", "п'ятнадцять", + "шістнадцять", "сімнадцять", "вісімнадцять", "дев'ятнадцять" + }; + + private static string[] tens = + { + "", "десять", "двадцять", "тридцять", "сорок", "п'ятдесят", + "шістдесят", "сімдесят", "вісімдесят", "дев'яносто" + }; + + private static string[] hunds = + { + "", "сто", "двісті", "триста", "чотириста", + "п'ятсот", "шістсот", "сімсот", "вісімсот", "дев'ятсот" + }; + + private static WordInfo thousands = new WordInfo(false, "тисяч", "тисячі", "тисяч"); + private static WordInfo millions = new WordInfo(true, "мільйон", "мільйона", "мільйонів"); + private static WordInfo milliards = new WordInfo(true, "мільярд", "мільярда", "мільярдів"); + private static WordInfo trillions = new WordInfo(true, "трильйон", "трильйона", "трильйонів"); + + protected override string GetFixedWords(bool male, long value) + { + string result = fixedWords[value]; + if (!male) + { + if (value == 1) + return "одна"; + if (value == 2) + return "дві"; + } + return result; + } + + protected override string GetTen(bool male, long value) + { + return tens[value]; + } + + protected override string GetHund(bool male, long value) + { + return hunds[value / 100]; + } + + protected override WordInfo GetThousands() + { + return thousands; + } + + protected override WordInfo GetMillions() + { + return millions; + } + + protected override WordInfo GetMilliards() + { + return milliards; + } + + protected override WordInfo GetTrillions() + { + return trillions; + } + + protected override CurrencyInfo GetCurrency(string currencyName) + { + currencyName = currencyName.ToUpper(); + if (currencyName == "RUR") + currencyName = "RUB"; + return currencyList[currencyName]; + } + + protected override string GetZero() + { + return "нуль"; + } + + protected override string GetMinus() + { + return "мінус"; + } + + protected override string Case(long value, WordInfo info) + { + value = value % 100; + if (value > GetFixedWordsCount()) + value = value % 10; + + switch (value) + { + case 1: + return info.one; + + case 2: + case 3: + case 4: + return info.two; + + default: + return info.many; + } + } + + static NumToWordsUkr() + { + currencyList = new Dictionary(4); + currencyList.Add("RUB", new CurrencyInfo( + new WordInfo(true, "рубль", "рубля", "рублів"), + new WordInfo(false, "копійка", "копійки", "копійок"))); + currencyList.Add("UAH", new CurrencyInfo( + new WordInfo(false, "гривня", "гривні", "гривень"), + new WordInfo(false, "копійка", "копійки", "копійок"))); + currencyList.Add("EUR", new CurrencyInfo( + new WordInfo(true, "євро", "євро", "євро"), + new WordInfo(true, "євроцент", "євроцента", "євроценту"))); + currencyList.Add("USD", new CurrencyInfo( + new WordInfo(true, "долар", "долара", "доларів"), + new WordInfo(true, "цент", "цента", "центів"))); + } + } +} \ No newline at end of file diff --git a/FastReport.Base/Functions/StdFunctions.cs b/FastReport.Base/Functions/StdFunctions.cs index 6e37a12a..45bf2235 100644 --- a/FastReport.Base/Functions/StdFunctions.cs +++ b/FastReport.Base/Functions/StdFunctions.cs @@ -912,16 +912,198 @@ public static string ToWordsNl(object value, string one, string many) return new NumToWordsNl().ConvertNumber(Convert.ToDecimal(value), true, one, many, many); } - #endregion + ///

+ /// Converts a numeric value to a indian numbering system string representation of that value. + /// + /// the currency value to convert + /// The string representation of the specified value. + public static string ToWordsIn(object value) + { + return ToWordsIn(value, "INR"); + } + /// + /// Converts a numeric value to a indian numbering system string representation of that value. + /// + /// he numeric value to convert. + /// The 3-digit ISO name of the currency, for example "INR". + /// + public static string ToWordsIn(object value,string currencyName) + { + return new NumToWordsIn().ConvertCurrency(Convert.ToDecimal(value), currencyName); + } - #region Program Flow - /// - /// Selects and returns a value from a list of arguments. - /// - /// A value between 1 and the number of elements passed in the "choice" argument. - /// Object parameter array. - /// One of the values in the "choice" argument. - public static object Choose(double index, params object[] choice) + /// + /// Converts a numeric value to a indian numbering system string representation of that value. + /// + /// The numeric value to convert. + /// The name in singular form, for example "page". + /// The name in plural form, for example "pages". + /// The string representation of the specified value. + public static string ToWordsIn(object value, string one, string many) + { + return new NumToWordsIn().ConvertNumber(Convert.ToDecimal(value), true, one, many, many); + } + + /// + /// Converts a numeric value to a ukrainian string representation of that value. + /// + /// The numeric value to convert. + /// The string representation of the specified value. + public static string ToWordsUkr(object value) + { + return ToWordsUkr(value,"UAH"); + } + + + /// + /// Converts a currency value to a ukrainian string representation of that value, + /// using the specified currency. + /// + /// The currency value to convert. + /// The 3-digit ISO name of the currency, for example "UAH". + /// The string representation of the specified value. + public static string ToWordsUkr(object value, string currencyName) + { + return new NumToWordsUkr().ConvertCurrency(Convert.ToDecimal(value), currencyName); + } + + /// + /// Converts a numeric value to a ukrainian string representation of that value. + /// + /// The numeric value to convert. + /// True if the name is of male gender. + /// The name in singular form, for example "сторінка". + /// The name in plural form, for example "сторінки". + /// The name in plural form, for example "сторінок". + /// The string representation of the specified value. + public static string ToWordsUkr(object value, bool male, string one, string two, string many) + { + return new NumToWordsUkr().ConvertNumber(Convert.ToDecimal(value), male, one, two, many); + } + + + /// + /// Converts a numeric value to a spanish string representation of that value. + /// + /// The numeric value to convert. + /// The string representation of the specified value. + public static string ToWordsSp(object value) + { + return ToWordsSp(value, "EUR"); + } + + /// + /// Converts a numeric value to a spanish representation of that value. + /// + /// he numeric value to convert. + /// The 3-digit ISO name of the currency, for example "EUR". + /// + public static string ToWordsSp(object value, string currencyName) + { + return new NumToWordsSp().ConvertCurrency(Convert.ToDecimal(value), currencyName); + } + + /// + /// Converts a numeric value to a spanish string representation of that value. + /// + /// The numeric value to convert. + /// True if the name is of male gender. + /// The name in singular form, for example "silla". + /// The name in plural form, for example "Sillas". + /// The name in plural form, for example "Sillas". + /// The string representation of the specified value. + public static string ToWordsSp(object value, string one, string many) + { + return new NumToWordsSp().ConvertNumber(Convert.ToDecimal(value), true, one, many, many); + } + + /// + /// Converts a numeric value to a persian string representation of that value. + /// + /// The numeric value to convert. + /// The string representation of the specified value. + public static string ToWordsPersian(object value) + { + return ToWordsPersian(value, "EUR"); + } + + /// + /// Converts a numeric value to a persian representation of that value. + /// + /// he numeric value to convert. + /// The 3-digit ISO name of the currency, for example "EUR". + /// + public static string ToWordsPersian(object value, string currencyName) + { + return new NumToWordsPersian().ConvertCurrency(Convert.ToDecimal(value), currencyName); + } + + /// + /// Converts a numeric value to a persian string representation of that value. + /// + /// The numeric value to convert. + /// True if the name is of male gender. + /// The name in singular form, for example "silla". + /// The name in plural form, for example "Sillas". + /// The name in plural form, for example "Sillas". + /// The string representation of the specified value. + public static string ToWordsPersian(object value, string one, string many) + { + return new NumToWordsPersian().ConvertNumber(Convert.ToDecimal(value), true, one, many, many); + } + + /// + /// Converts a value to an english (US) alphabet string representation of that value. + /// + /// The value to convert. + /// The alphabet string representation of the specified value. + public static string ToLetters(object value) + { + return ToLetters(value, false); + } + + /// + /// Converts a value to an english (US) alphabet string representation of that value. + /// + /// The value to convert. + /// Bool indicating that letters should be in upper registry. + /// The alphabet string representation of the specified value. + public static string ToLetters(object value, bool isUpper) + { + return new NumToLettersEn().ConvertNumber(Convert.ToInt32(value), isUpper); + } + + /// + /// Converts a value to a russian alphabet string representation of that value. + /// + /// The value to convert. + /// The alphabet string representation of the specified value. + public static string ToLettersRu(object value) + { + return ToLettersRu(value, false); + } + + /// + /// Converts a value to a russian alphabet string representation of that value. + /// + /// The value to convert. + /// Bool indicating that letters should be in upper registry. + /// The alphabet string representation of the specified value. + public static string ToLettersRu(object value, bool isUpper) + { + return new NumToLettersRu().ConvertNumber(Convert.ToInt32(value), isUpper); + } + + #endregion + + #region Program Flow + /// + /// Selects and returns a value from a list of arguments. + /// + /// A value between 1 and the number of elements passed in the "choice" argument. + /// Object parameter array. + /// One of the values in the "choice" argument. + public static object Choose(double index, params object[] choice) { int ind = (int)index - 1; if (ind < 0 || ind >= choice.Length) @@ -1103,7 +1285,10 @@ internal static void Register() RegisteredObjects.AddFunction(myConv.GetMethod("ToWords", new Type[] { typeof(object) }), "Conversion,ToWords"); RegisteredObjects.AddFunction(myConv.GetMethod("ToWords", new Type[] { typeof(object), typeof(string) }), "Conversion,ToWords"); RegisteredObjects.AddFunction(myConv.GetMethod("ToWords", new Type[] { typeof(object), typeof(string), typeof(string) }), "Conversion,ToWords"); - RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsDe", new Type[] { typeof(object) }), "Conversion,ToWordsDe"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsIn", new Type[] { typeof(object) }), "Conversion,ToWordsIn"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsIn", new Type[] { typeof(object),typeof(string) }), "Conversion,ToWordsIn"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsIn", new Type[] { typeof(object), typeof(string),typeof(string) }), "Conversion,ToWordsIn"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsDe", new Type[] { typeof(object) }), "Conversion,ToWordsDe"); RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsDe", new Type[] { typeof(object), typeof(string) }), "Conversion,ToWordsDe"); RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsDe", new Type[] { typeof(object), typeof(string), typeof(string) }), "Conversion,ToWordsDe"); RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsEnGb", new Type[] { typeof(object) }), "Conversion,ToWordsEnGb"); @@ -1121,10 +1306,23 @@ internal static void Register() RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsRu", new Type[] { typeof(object) }), "Conversion,ToWordsRu"); RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsRu", new Type[] { typeof(object), typeof(string) }), "Conversion,ToWordsRu"); RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsRu", new Type[] { typeof(object), typeof(bool), typeof(string), typeof(string), typeof(string) }), "Conversion,ToWordsRu"); - #endregion - - #region Program Flow - RegisteredObjects.AddFunctionCategory("ProgramFlow", "Functions,ProgramFlow"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsUkr",new Type[]{typeof(object)}),"Conversion,ToWordsUkr"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsUkr", new Type[] { typeof(object), typeof(string) }), "Conversion,ToWordsUkr"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsUkr", new Type[] { typeof(object), typeof(bool), typeof(string), typeof(string), typeof(string) }), "Conversion,ToWordsUkr"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsSp", new Type[] { typeof(object), typeof(string) }), "Conversion,ToWordsSp"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsSp", new Type[] { typeof(object) }), "Conversion,ToWordsSp"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsSp", new Type[] { typeof(object), typeof(string), typeof(string) }), "Conversion,ToWordsSp"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsPersian", new Type[] { typeof(object), typeof(string) }), "Conversion,ToWordsPersian"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsPersian", new Type[] { typeof(object) }), "Conversion,ToWordsPersian"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToWordsPersian", new Type[] { typeof(object), typeof(string), typeof(string) }), "Conversion,ToWordsPersian"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToLetters", new Type[] { typeof(object) }), "Conversion,ToLetters"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToLetters", new Type[] { typeof(object), typeof(bool) }), "Conversion,ToLetters"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToLettersRu", new Type[] { typeof(object) }), "Conversion,ToLettersRu"); + RegisteredObjects.AddFunction(myConv.GetMethod("ToLettersRu", new Type[] { typeof(object), typeof(bool) }), "Conversion,ToLettersRu"); + #endregion + + #region Program Flow + RegisteredObjects.AddFunctionCategory("ProgramFlow", "Functions,ProgramFlow"); Type misc = typeof(StdFunctions); RegisteredObjects.AddFunction(misc.GetMethod("Choose"), "ProgramFlow"); RegisteredObjects.AddFunction(misc.GetMethod("IIf"), "ProgramFlow"); diff --git a/FastReport.Base/PictureObjectBase.cs b/FastReport.Base/PictureObjectBase.cs index 6ddd990b..058653e3 100644 --- a/FastReport.Base/PictureObjectBase.cs +++ b/FastReport.Base/PictureObjectBase.cs @@ -5,6 +5,7 @@ using System.Drawing; using System.Drawing.Design; using System.IO; +using System.Runtime.InteropServices; using System.Windows.Forms; namespace FastReport @@ -846,7 +847,7 @@ internal virtual void DrawImageInternal(FRPaintEventArgs e, RectangleF drawRect) bool rotate = Angle == 90 || Angle == 270; float imageWidth = ImageWidth;//rotate ? Image.Height : Image.Width; float imageHeight = ImageHeight;//rotate ? Image.Width : Image.Height; - + PointF upperLeft; PointF upperRight; PointF lowerLeft; @@ -857,35 +858,44 @@ internal virtual void DrawImageInternal(FRPaintEventArgs e, RectangleF drawRect) // cant work with negative transforms so need to fix it #if NETSTANDARD2_0 || NETSTANDARD2_1 - + System.Drawing.Drawing2D.Matrix matrixBack = e.Graphics.Transform; + /* + Временное решение (т.к. не удалось найти универсального), которое устраняет проблемы с экспортом картинок в Excel2007 на Windows, но на Linux не работает. + */ + if (!Config.IsWindows) + { + System.Drawing.Drawing2D.Matrix matrixTemp = new System.Drawing.Drawing2D.Matrix( + matrixBack.Elements[0], + matrixBack.Elements[1], + matrixBack.Elements[2], + matrixBack.Elements[3], + 0, + 0 + ); - System.Drawing.Drawing2D.Matrix matrixTemp = new System.Drawing.Drawing2D.Matrix( - matrixBack.Elements[0], - matrixBack.Elements[1], - matrixBack.Elements[2], - matrixBack.Elements[3], - 0, - 0 - ); - - upperLeft.X += matrixBack.OffsetX; - upperLeft.Y += matrixBack.OffsetY; + upperLeft.X += matrixBack.OffsetX; + upperLeft.Y += matrixBack.OffsetY; - upperRight.X += matrixBack.OffsetX; - upperRight.Y += matrixBack.OffsetY; + upperRight.X += matrixBack.OffsetX; + upperRight.Y += matrixBack.OffsetY; - lowerLeft.X += matrixBack.OffsetX; - lowerLeft.Y += matrixBack.OffsetY; + lowerLeft.X += matrixBack.OffsetX; + lowerLeft.Y += matrixBack.OffsetY; - e.Graphics.Transform = matrixTemp; + e.Graphics.Transform = matrixTemp; + } #endif DrawImageInternal2(e.Graphics, upperLeft, upperRight, lowerLeft); #if NETSTANDARD2_0 || NETSTANDARD2_1 - e.Graphics.Transform = matrixBack; + if (!Config.IsWindows) + { + e.Graphics.Transform = matrixBack; + } #endif + } #endif diff --git a/FastReport.Base/PolyLineObject.cs b/FastReport.Base/PolyLineObject.cs index 151d0378..a682ff57 100644 --- a/FastReport.Base/PolyLineObject.cs +++ b/FastReport.Base/PolyLineObject.cs @@ -799,7 +799,12 @@ private string Round(float value) internal PolyPoint Clone() { - return new PolyPoint(x, y); + PolyPoint result = new PolyPoint(x, y); + if (LeftCurve != null) + result.LeftCurve = LeftCurve.Clone(); + if (RightCurve != null) + result.RightCurve = RightCurve.Clone(); + return result; } #endregion Private Methods diff --git a/FastReport.Base/Preview/Dictionary.cs b/FastReport.Base/Preview/Dictionary.cs index cdfacc93..e131303f 100644 --- a/FastReport.Base/Preview/Dictionary.cs +++ b/FastReport.Base/Preview/Dictionary.cs @@ -58,7 +58,14 @@ public Base GetObject(string name) { DictionaryItem item; if (names.TryGetValue(name, out item)) - return item.CloneObject(name); + { + // return item.CloneObject(name); + if(item.OriginalComponent != null) + item.OriginalComponent.SetReport(this.preparedPages.Report); + Base result = item.CloneObject(name); + //result.SetReport(this); + return result; + } else return null; diff --git a/FastReport.Base/Preview/PreparedPagePostprocessor.cs b/FastReport.Base/Preview/PreparedPagePostprocessor.cs index 42bca01b..84810297 100644 --- a/FastReport.Base/Preview/PreparedPagePostprocessor.cs +++ b/FastReport.Base/Preview/PreparedPagePostprocessor.cs @@ -120,6 +120,8 @@ public void Postprocess(ReportPage page) for (int i = 0; i < allObjects.Count; i++) { Base c = allObjects[i]; + if (c.Report == null) + c.SetReport(page.Report); c.ExtractMacros(); if (c is BandBase) diff --git a/FastReport.Base/Preview/PreparedPages.cs b/FastReport.Base/Preview/PreparedPages.cs index 4e47e2f2..05b8f260 100644 --- a/FastReport.Base/Preview/PreparedPages.cs +++ b/FastReport.Base/Preview/PreparedPages.cs @@ -458,8 +458,8 @@ public void Save(Stream stream) doc.Root.SetProp("ReportInfo.Name", Report.ReportInfo.Name); doc.Root.SetProp("ReportInfo.Author", Report.ReportInfo.Author); doc.Root.SetProp("ReportInfo.Description", Report.ReportInfo.Description); - doc.Root.SetProp("ReportInfo.Created", DateTime.Now.ToString()); - doc.Root.SetProp("ReportInfo.Modified", DateTime.Now.ToString()); + doc.Root.SetProp("ReportInfo.Created", SystemFake.DateTime.Now.ToString()); + doc.Root.SetProp("ReportInfo.Modified", SystemFake.DateTime.Now.ToString()); doc.Root.SetProp("ReportInfo.CreatorVersion", Report.ReportInfo.CreatorVersion); XmlItem pages = doc.Root.Add(); diff --git a/FastReport.Base/Preview/SourcePages.cs b/FastReport.Base/Preview/SourcePages.cs index 569cd8e5..0aa83c5d 100644 --- a/FastReport.Base/Preview/SourcePages.cs +++ b/FastReport.Base/Preview/SourcePages.cs @@ -33,31 +33,14 @@ private Base CloneObjects(Base source, Base parent) // create clone object and assign all properties from source string baseName = ""; string objName; -#if MONO - if (source is RichObject && (source as RichObject).ConvertRichText == true) - { - RichObject rich = source as RichObject; - float h; - List clone_list = rich.Convert2ReportObjects(out h); - - int i = 1; - foreach(Base clone_item in clone_list) - { - baseName = clone_item.BaseName[0].ToString().ToLower(); - clone_item.Name = rich.Name + "_" + i; - objName = "Page" + pages.Count.ToString() + "." + clone_item.Name; - clone_item.Alias = preparedPages.Dictionary.AddUnique(baseName, objName, clone_item); - source.Alias = clone_item.Alias; - clone_item.Parent = parent; - i++; - } - return null; - } -#endif Base clone = Activator.CreateInstance(source.GetType()) as Base; using (XmlItem xml = new XmlItem()) using (FRWriter writer = new FRWriter(xml)) +#if MONO + using (FRReader reader = new FRReader(source.Report, xml)) +#else using (FRReader reader = new FRReader(null, xml)) +#endif { reader.DeserializeFrom = SerializeTo.SourcePages; writer.SaveChildren = false; @@ -91,6 +74,9 @@ private Base CloneObjects(Base source, Base parent) CloneObjects(c, clone); } clone.Parent = parent; +#if MONO + clone.SetReport(source.Report); +#endif return clone; } #endregion diff --git a/FastReport.Base/Report.cs b/FastReport.Base/Report.cs index 93b32b3d..c29596cb 100644 --- a/FastReport.Base/Report.cs +++ b/FastReport.Base/Report.cs @@ -846,9 +846,8 @@ private string[] DefaultAssemblies "System.Xml.dll", -#if NETSTANDARD "FastReport.Compat.dll", -#else +#if !NETSTANDARD "System.Windows.Forms.dll", #endif @@ -1426,7 +1425,7 @@ protected virtual object CalcExpression(string expression, Variant value) // expression not found. Probably it was added after the start of the report. // Compile new assembly containing this expression. - AssemblyDescriptor descriptor = new AssemblyDescriptor(this, CodeHelper.EmptyScript()); + AssemblyDescriptor descriptor = new AssemblyDescriptor(this, ScriptText); assemblies.Add(descriptor); descriptor.AddObjects(); descriptor.AddSingleExpression(expression); @@ -2352,6 +2351,40 @@ public bool Prepare(bool append) } } + /// + /// Prepares the report with pages limit. + /// + /// Pages limit. The number of pages equal or less will be prepared. + /// true if report was prepared succesfully. + public bool Prepare(int pagesLimit) + { + SetRunning(true); + try + { + ClearPreparedPages(); + SetPreparedPages(new Preview.PreparedPages(this)); + engine = new ReportEngine(this); + + if (!Config.WebMode) + StartPerformanceCounter(); + + try + { + Compile(); + return Engine.Run(true, false, true, pagesLimit); + } + finally + { + if (!Config.WebMode) + StopPerformanceCounter(); + } + } + finally + { + SetRunning(false); + } + } + /// /// For internal use only. /// diff --git a/FastReport.Base/ReportComponentBase.cs b/FastReport.Base/ReportComponentBase.cs index c9912fef..9445e5fc 100644 --- a/FastReport.Base/ReportComponentBase.cs +++ b/FastReport.Base/ReportComponentBase.cs @@ -970,6 +970,13 @@ public virtual void GetData() public override string[] GetExpressions() { List expressions = new List(); + + string[] baseExpressions = base.GetExpressions(); + if (baseExpressions != null) + { + expressions.AddRange(baseExpressions); + } + if (!String.IsNullOrEmpty(Hyperlink.Expression)) expressions.Add(Hyperlink.Expression); if (!String.IsNullOrEmpty(Bookmark)) @@ -979,7 +986,21 @@ public override string[] GetExpressions() { if (ExportableExpression.StartsWith("[") && ExportableExpression.EndsWith("]")) { - expressions.Add(ExportableExpression.Substring(1, ExportableExpression.Length - 2)); + string tempExpression = ExportableExpression.Substring(1, ExportableExpression.Length - 2); + int firstOpen = tempExpression.IndexOf("["); + int firstClose = tempExpression.IndexOf("]"); + int lastOpen = tempExpression.LastIndexOf("["); + int lastClose = tempExpression.LastIndexOf("]"); + if ((firstOpen < 0 && firstClose >= 0) || (lastOpen >= 0 && lastClose < 0) + || (firstOpen >= 0 && firstClose >= 0 && firstClose < firstOpen) + || (lastOpen >= 0 && lastClose >= 0 && lastOpen > lastClose)) + { + expressions.Add(ExportableExpression); + } + else + { + expressions.Add(tempExpression); + } } else { diff --git a/FastReport.Base/ReportInfo.cs b/FastReport.Base/ReportInfo.cs index 0ee2ca1e..16ff98f6 100644 --- a/FastReport.Base/ReportInfo.cs +++ b/FastReport.Base/ReportInfo.cs @@ -208,8 +208,8 @@ public void Clear() if (picture != null) picture.Dispose(); picture = null; - created = DateTime.Now; - modified = DateTime.Now; + created = SystemFake.DateTime.Now; + modified = SystemFake.DateTime.Now; savePreviewPicture = false; previewPictureRatio = 0.1f; creatorVersion = CurrentVersion; @@ -231,7 +231,7 @@ internal void Serialize(FRWriter writer, ReportInfo c) if (!writer.AreEqual(Picture, c.Picture)) writer.WriteValue("ReportInfo.Picture", Picture); writer.WriteValue("ReportInfo.Created", Created); - modified = DateTime.Now; + modified = SystemFake.DateTime.Now; writer.WriteValue("ReportInfo.Modified", Modified); if (SavePreviewPicture != c.SavePreviewPicture) writer.WriteBool("ReportInfo.SavePreviewPicture", SavePreviewPicture); diff --git a/FastReport.Base/Utils/Config.cs b/FastReport.Base/Utils/Config.cs index 1546cb21..fac12630 100644 --- a/FastReport.Base/Utils/Config.cs +++ b/FastReport.Base/Utils/Config.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.IO; using System.Reflection; +using System.Runtime.InteropServices; namespace FastReport.Utils { @@ -36,12 +37,17 @@ public static partial class Config private static string FTempFolder = null; private static string systemTempFolder = null; private static bool FStringOptimization = false; + private static bool FWebMode; private static bool preparedCompressed = true; private static bool disableHotkeys = false; private static bool disableBacklight = false; private static bool enableScriptSecurity = false; private static ScriptSecurityProperties scriptSecurityProps = null; +#if NETSTANDARD2_0 || NETSTANDARD2_1 + private static readonly bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); +#endif + #endregion Private Fields #region Public Properties @@ -53,6 +59,14 @@ public static bool IsRunningOnMono get { return FIsRunningOnMono; } } +#if NETSTANDARD2_0 || NETSTANDARD2_1 + public static bool IsWindows + { + get { return isWindows; } + } +#endif + + /// /// Gets or sets the optimization of strings. Is experimental feature. /// @@ -100,7 +114,7 @@ public static string Folder get { return FFolder; } set { FFolder = value; } } - + /// /// Gets or sets the path used to font.list file. /// @@ -240,23 +254,20 @@ internal static void Init() { FIsRunningOnMono = Type.GetType("Mono.Runtime") != null; -#if !(NETSTANDARD2_0 || NETSTANDARD2_1) - string processName = System.Diagnostics.Process.GetCurrentProcess().ProcessName; - WebMode = String.Compare(processName, "iisexpress") == 0 || - String.Compare(processName, "w3wp") == 0; + InitWebMode(); +#if !NETSTANDARD if (!WebMode) LoadConfig(); -#else - WebMode = true; #endif if (WebMode) { -#if !COMMUNITY - RestoreExportOptions(); enableScriptSecurity = true; // don't throw event scriptSecurityProps = new ScriptSecurityProperties(); -#endif } + +#if !COMMUNITY + RestoreExportOptions(); +#endif LoadPlugins(); // init TextRenderingHint.SystemDefault @@ -270,6 +281,25 @@ internal static void Init() } } + private static void InitWebMode() + { + string processName = System.Diagnostics.Process.GetCurrentProcess().ProcessName; + +#if NETSTANDARD + ConfigSetsWebMode(String.Compare(processName, "dotnet") == 0); +#else + ConfigSetsWebMode(String.Compare(processName, "iisexpress") == 0 || + String.Compare(processName, "w3wp") == 0); +#endif + } + + // If we/user sets 'WebMode = true' before checks in Config.cs - Config shouln't change it (because check may be incorrect) + private static void ConfigSetsWebMode(bool value) + { + if (!FWebMode) + WebMode = value; + } + internal static void WriteLogString(string s) { WriteLogString(s, false); @@ -299,13 +329,13 @@ internal static void OnScriptCompile(ScriptSecurityEventArgs e) } } - #endregion Internal Methods +#endregion Internal Methods - #region Private Methods +#region Private Methods private static string GetTempFileName() { - return Path.Combine(GetTempFolder(), DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss-") + Path.GetRandomFileName()); + return Path.Combine(GetTempFolder(), SystemFake.DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss-") + Path.GetRandomFileName()); } private static string GetTempPath() @@ -392,9 +422,6 @@ private static void LoadConfig() RestoreDefaultLanguage(); RestoreUIOptions(); RestorePreviewSettings(); -#if !COMMUNITY - RestoreExportOptions(); -#endif Res.LoadDefaultLocale(); AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit); } diff --git a/FastReport.Base/Utils/Converter.cs b/FastReport.Base/Utils/Converter.cs index a027825f..6886e8ab 100644 --- a/FastReport.Base/Utils/Converter.cs +++ b/FastReport.Base/Utils/Converter.cs @@ -80,6 +80,11 @@ public static string ToString(object value) return FastReport.TypeConverters.FontConverter.Instance.ConvertToInvariantString(value); } #endif + if(value is System.Drawing.Imaging.ImageFormat) + { + var imageFormat = value as System.Drawing.Imaging.ImageFormat; + return imageFormat.ToString(); + } return TypeDescriptor.GetConverter(value).ConvertToInvariantString(value); } diff --git a/FastReport.Base/Utils/FRReader.cs b/FastReport.Base/Utils/FRReader.cs index 7ea6c25c..7d881c80 100644 --- a/FastReport.Base/Utils/FRReader.cs +++ b/FastReport.Base/Utils/FRReader.cs @@ -80,6 +80,11 @@ public SerializeTo DeserializeFrom set { deserializeFrom = value; } } + public Report Report + { + get { return report; } + } + private XmlItem GetRoot(XmlItem item, int count) { if (count < 0 || item.Parent==null) diff --git a/FastReport.Base/Utils/Zip.cs b/FastReport.Base/Utils/Zip.cs index 699c6182..39fa944e 100644 --- a/FastReport.Base/Utils/Zip.cs +++ b/FastReport.Base/Utils/Zip.cs @@ -303,7 +303,7 @@ public void Clear() public ZipFileItem() { stream = new MemoryStream(); - fileDateTime = GetDosDateTime(DateTime.Now); + fileDateTime = GetDosDateTime(SystemFake.DateTime.Now); disk = false; } @@ -311,7 +311,7 @@ public ZipFileItem(string fileName, Stream stream) { this.stream = stream; name = fileName; - fileDateTime = GetDosDateTime(DateTime.Now); + fileDateTime = GetDosDateTime(SystemFake.DateTime.Now); disk = false; } diff --git a/FastReport.Core.Web/Application/WebReport.Exports.cs b/FastReport.Core.Web/Application/WebReport.Exports.cs index fafdf3ad..fd7f52bb 100644 --- a/FastReport.Core.Web/Application/WebReport.Exports.cs +++ b/FastReport.Core.Web/Application/WebReport.Exports.cs @@ -51,14 +51,18 @@ partial class WebReport /// Switches a visibility of XML (Excel) export in toolbar. ///
public bool ShowXmlExcelExport { get; set; } = true; - ///// - ///// Switches a visibility of DBF export in toolbar. - ///// - //public bool ShowDbfExport { get; set; } = false; /// - /// Switch visibility the CSV (comma separated values) export in toolbar. + /// Switches a visibility of DBF export in toolbar. + /// + public bool ShowDbfExport { get; set; } = false; + /// + /// Switches visibility the CSV (comma separated values) export in toolbar. /// public bool ShowCsvExport { get; set; } = true; + /// + /// Switches visibility the MHT export in toolbar. + /// + public bool ShowMhtExport { get; set; } = false; #endif } } diff --git a/FastReport.Core.Web/Application/WebReport.cs b/FastReport.Core.Web/Application/WebReport.cs index 414159ee..b0b46248 100644 --- a/FastReport.Core.Web/Application/WebReport.cs +++ b/FastReport.Core.Web/Application/WebReport.cs @@ -7,6 +7,7 @@ using System.Linq; using FastReport.Web.Controllers; using FastReport.Web.Application; +using System.Drawing; namespace FastReport.Web { @@ -147,7 +148,29 @@ public bool ReportPrepared public string Height { get; set; } = ""; public bool Pictures { get; set; } = true; public bool EmbedPictures { get; set; } = false; + + + #region ToolbarSettings public bool ShowToolbar { get; set; } = true; + public bool ShowPrevButton { get; set; } = true; + public bool ShowNextButton { get; set; } = true; + public bool ShowFirstButton { get; set; } = true; + public bool ShowLastButton { get; set; } = true; + public bool ShowExports { get; set; } = true; + public bool ShowRefreshButton { get; set; } = true; + public bool ShowZoomButton { get; set; } = true; + + public bool ShowPrint { get; set; } = true; + public bool PrintInHtml { get; set; } = true; +#if !OPENSOURCE + public bool PrintInPdf { get; set; } = true; +#endif + + public bool ShowBottomToolbar { get; set; } = false; + + public Color ToolbarColor { get; set; } = Color.LightGray; + + #endregion public float Zoom { get; set; } = 1.0f; public bool Debug { get; set; } = false; internal bool Canceled { get; set; } = false; @@ -206,6 +229,18 @@ public async Task Render() return Render(false); } + public void LoadPrepared(string filename) + { + Report.LoadPrepared(filename); + ReportPrepared = true; + } + + public void LoadPrepared(Stream stream) + { + Report.LoadPrepared(stream); + ReportPrepared = true; + } + internal HtmlString Render(bool renderBody) { switch (Mode) diff --git a/FastReport.Core.Web/Application/WebReportHtml.cs b/FastReport.Core.Web/Application/WebReportHtml.cs index 55111244..949d15a4 100644 --- a/FastReport.Core.Web/Application/WebReportHtml.cs +++ b/FastReport.Core.Web/Application/WebReportHtml.cs @@ -122,12 +122,12 @@ public IActionResult PrintHtml() internal void Dialogs(HttpRequest request) { +#if DIALOGS string dialogN = request.Query["dialog"]; string controlName = request.Query["control"]; string eventName = request.Query["event"]; string data = request.Query["data"]; -#if DIALOGS Dialog.SetDialogs(dialogN, controlName, eventName, data); #endif } diff --git a/FastReport.Core.Web/Controllers/ResourceController.cs b/FastReport.Core.Web/Controllers/ResourceController.cs index 70bade69..4e4a3789 100644 --- a/FastReport.Core.Web/Controllers/ResourceController.cs +++ b/FastReport.Core.Web/Controllers/ResourceController.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Net.Http; using System.Text; -using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Http; diff --git a/FastReport.Core.Web/FastReport.Web.csproj b/FastReport.Core.Web/FastReport.Web.csproj index cc12cfd4..258998c9 100644 --- a/FastReport.Core.Web/FastReport.Web.csproj +++ b/FastReport.Core.Web/FastReport.Web.csproj @@ -32,7 +32,7 @@ $(DemoDescription)
- + diff --git a/FastReport.Core.Web/Templates/main.cs b/FastReport.Core.Web/Templates/main.cs index 6320c68c..b85af1fa 100644 --- a/FastReport.Core.Web/Templates/main.cs +++ b/FastReport.Core.Web/Templates/main.cs @@ -41,6 +41,8 @@ string template_render(bool renderBody) string odtTxt = Res.Get("Odt"); string xmlTxt = Res.Get("Xml"); string csvTxt = Res.Get("Csv"); + string dbfTxt = Res.Get("Dbf"); + string mhtTxt = Res.Get("Mht"); return $@"
@@ -57,12 +59,22 @@ string template_render(bool renderBody)
- {template_toolbar(saveTxt, reloadTxt, preparedTxt, printTxt, printFromBrowserTxt, - printFromPdf, zoomTxt, firstPageTxt, previousPageTxt, currentPageTxt, nextPageTxt, + {(ShowBottomToolbar?$@" +{template_body(renderBody)} +{template_toolbar(saveTxt, reloadTxt, preparedTxt, printTxt, printFromBrowserTxt, + printFromPdf, zoomTxt, firstPageTxt, previousPageTxt, currentPageTxt, nextPageTxt, lastPageTxt, totalPagesTxt, pdfTxt, excel2007Txt, word2007Txt, pptxTxt, txtTxt, rtfTxt, xpsTxt, odsTxt, - odtTxt, xmlTxt, csvTxt)} + odtTxt, xmlTxt, csvTxt, dbfTxt, mhtTxt)}" + :$@" +{template_toolbar(saveTxt, reloadTxt, preparedTxt, printTxt, printFromBrowserTxt, + printFromPdf, zoomTxt, firstPageTxt, previousPageTxt, currentPageTxt, nextPageTxt, + lastPageTxt, totalPagesTxt, pdfTxt, excel2007Txt, word2007Txt, pptxTxt, txtTxt, rtfTxt, xpsTxt, odsTxt, + odtTxt, xmlTxt, csvTxt, dbfTxt, mhtTxt)} +{template_body(renderBody)}")} + + - {template_body(renderBody)} + "; } diff --git a/FastReport.Core.Web/Templates/script.cs b/FastReport.Core.Web/Templates/script.cs index d346045a..9067c640 100644 --- a/FastReport.Core.Web/Templates/script.cs +++ b/FastReport.Core.Web/Templates/script.cs @@ -106,7 +106,8 @@ string template_script() => $@" }}, goto: function (page) {{ - this._reload('&skipPrepare=yes&goto=' + page); + this._reload('&skipPrepare=yes&goto=' + page);"+ + (ShowBottomToolbar? $@"document.getElementsByClassName('{template_FR}-body')[0].scrollIntoView({{behavior:""smooth""}});" : "")+$@" }}, click: function (el, kind, value) {{ diff --git a/FastReport.Core.Web/Templates/style.cs b/FastReport.Core.Web/Templates/style.cs index 3c28dac2..d8066131 100644 --- a/FastReport.Core.Web/Templates/style.cs +++ b/FastReport.Core.Web/Templates/style.cs @@ -53,7 +53,7 @@ string template_style() => $@" .{template_FR}-toolbar {{ flex-shrink: 0; font-family: Verdana,Arial,sans-serif; - background-color: #f1f1f1; + background-color: {ToolbarColor.Name}; {(Tabs.Count > 1 ? "" : "box-shadow: 0px 3px 4px -2px rgba(0, 0, 0, 0.2);")} display: flex; /* flex-wrap: wrap; */ diff --git a/FastReport.Core.Web/Templates/toolbar.cs b/FastReport.Core.Web/Templates/toolbar.cs index 035546bc..087c8bde 100644 --- a/FastReport.Core.Web/Templates/toolbar.cs +++ b/FastReport.Core.Web/Templates/toolbar.cs @@ -14,58 +14,63 @@ string template_toolbar(string saveTxt = "Save", string reloadTxt = "Reload", st string pdfTxt = "Adobe PDF", string excel2007Txt = "Microsoft Excel 2007", string word2007Txt = "Microsoft Word 2007", string pptxTxt = "Microsoft PowerPoint 2007", string txtTxt = "Text File/Matrix Printer", string rtfTxt = "Rich Text", string xpsTxt = "Microsoft XPS", string odsTxt = "OpenOffice Calc", string odtTxt = "OpenOffice Writer", - string xmlTxt = "XML (Excel) table", string csvTxt = "CSV file") + string xmlTxt = "XML (Excel) table", string csvTxt = "CSV file", string dbfTxt = "DBF table", string mhtTxt = "MHT file") { if (!ShowToolbar) return ""; + var toolbarExportItem = $@"
+ +
" + + (ShowPreparedReport ? $@"{preparedTxt}" : "") +#if !OPENSOURCE + + (ShowPdfExport ? $@"{pdfTxt}" : "") + + (ShowExcel2007Export ? $@"{excel2007Txt}" : "") + + (ShowWord2007Export ? $@"{word2007Txt}" : "") + + (ShowPowerPoint2007Export ? $@"{pptxTxt}" : "") + + (ShowTextExport ? $@"{txtTxt}" : "") + + (ShowRtfExport ? $@"{rtfTxt}" : "") + + (ShowXpsExport ? $@"{xpsTxt}" : "") + + (ShowOdsExport ? $@"{odsTxt}" : "") + + (ShowOdtExport ? $@"{odtTxt}" : "") + + (ShowXmlExcelExport ? $@"{xmlTxt}" : "") + + (ShowDbfExport ? $@"{dbfTxt}": "") + + (ShowCsvExport ? $@"{csvTxt}" : "") + + (ShowMhtExport ? $@"{mhtTxt}" : "") +#endif + + "
" + ; + var toolbarPrintItem = $@"
+ +
+ " + + (PrintInHtml ? $@"{printFromBrowserTxt} + " : "") + +#if !OPENSOURCE + (PrintInPdf ? $@"{printFromPdf} + " : "") + +#endif + $@"
+
"; var currentZoom = Zoom * 100; var selectedZoom1 = $@"
"; var selectedZoom2 = $@"
"; var isFirstPage = CurrentPageIndex == 0; var isLastPage = CurrentPageIndex >= TotalPages - 1; - + string templateToolbar = $@"
-
+{(ShowRefreshButton ? $@"
-
+
" : "")} -
- -
" + - (ShowPreparedReport ? $@"{preparedTxt}" : "") + -#if !OPENSOURCE - (ShowPdfExport ? $@"{pdfTxt}": "") + - (ShowExcel2007Export ? $@"{excel2007Txt}": "") + - (ShowWord2007Export ? $@"{word2007Txt}": "") + - (ShowPowerPoint2007Export ? $@"{pptxTxt}": "") + - (ShowTextExport ? $@"{txtTxt}": "") + - (ShowRtfExport ? $@"{rtfTxt}": "") + - (ShowXpsExport ? $@"{xpsTxt}": "") + - (ShowOdsExport ? $@"{odsTxt}": "") + - (ShowOdtExport ? $@"{odtTxt}": "") + - (ShowXmlExcelExport ? $@"{xmlTxt}": "") + - //(ShowDbfExport ? $@"": "") + - (ShowCsvExport ? $@"{csvTxt}": "") + -#endif - $@"
-
+{(ShowExports ? $"{toolbarExportItem}" : "")} -
- -
- {printFromBrowserTxt} - " + -#if !OPENSOURCE - $@"{printFromPdf} - " + -#endif - $@"
-
-
+{(ShowPrint ? $"{toolbarPrintItem}" : "")} + +{(ShowZoomButton ? $@" +
" : "")} + {((SinglePage || TotalPages < 2) ? "" : $@" - -
+ {(ShowFirstButton ? $@"
-
- -
+
" : "")} + +{(ShowPrevButton ? $@"
-
+
" : "")} +
TotalPages ? TotalPages : (CurrentPageIndex + 1))}"" onchange=""{template_FR}.goto(document.getElementsByClassName('{template_FR}-current-page-input')[0].value);"" title=""{currentPageTxt}""> @@ -97,17 +103,19 @@ string template_toolbar(string saveTxt = "Save", string reloadTxt = "Reload", st
+
-
+{(ShowNextButton ? $@"
-
- -
+
" : "")} + +{(ShowLastButton ? $@"
-
+
" : "")} + ")}
diff --git a/FastReport.OpenSource/FastReport.OpenSource.csproj b/FastReport.OpenSource/FastReport.OpenSource.csproj index 4bf3f937..dba9a72d 100644 --- a/FastReport.OpenSource/FastReport.OpenSource.csproj +++ b/FastReport.OpenSource/FastReport.OpenSource.csproj @@ -33,23 +33,24 @@ Various report objects will allow your report to look exactly how you want it to: 13 types of bands, 25 types of barcodes, table object, shapes, line, PolyLine, Polygon and many more. https://github.com/FastReports/FastReport - - TRACE;DEBUG;DOTNET_4; + + + TRACE;DOTNET_4 - - TRACE;DOTNET_4; + + $(DefineConstants);DEBUG; + + + - - - - - - + + + + - diff --git a/FastReport.OpenSource/Utils/Config.Core.cs b/FastReport.OpenSource/Utils/Config.Core.cs index 79156fc4..6cfd354b 100644 --- a/FastReport.OpenSource/Utils/Config.Core.cs +++ b/FastReport.OpenSource/Utils/Config.Core.cs @@ -17,7 +17,6 @@ public static bool FullTrust /// /// Gets a value that determines whether to disable some functionality to run in web mode. - /// Set method does nothing. /// /// /// Use this property if you use FastReport in ASP.Net. Set this property to true before @@ -27,10 +26,11 @@ public static bool WebMode { get { - return true; + return FWebMode; } set { + FWebMode = value; } } diff --git a/FastReport/Resources/en.xml b/FastReport/Resources/en.xml index b3727b78..d4fc4002 100644 --- a/FastReport/Resources/en.xml +++ b/FastReport/Resources/en.xml @@ -322,7 +322,7 @@ - + @@ -1935,6 +1935,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2132,31 +2196,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2501,8 +2566,11 @@ - - + + + + + diff --git a/UsedPackages.version b/UsedPackages.version index 08293db0..adf52e48 100644 --- a/UsedPackages.version +++ b/UsedPackages.version @@ -3,22 +3,34 @@ - 2020.3.8 + 2020.4.2 - 2020.3.8 + 2020.4.2 + + [4.6.1,) + + + [4.4.0,) + + + 4.5.2 + + + 4.5.1 + - 2020.3.17 + 2021.1.0 - 2020.3.17 + 2021.1.0 - 2020.3.17 + 2021.1.0 - 2020.3.17 + 2021.1.0