diff --git a/FastReport.Base/BandBase.cs b/FastReport.Base/BandBase.cs
index fe294ef8..eeaa53a2 100644
--- a/FastReport.Base/BandBase.cs
+++ b/FastReport.Base/BandBase.cs
@@ -621,6 +621,12 @@ internal void FixHeightWithComponentsShift(float deltaY)
}
}
+ ///
+ public override List Validate()
+ {
+ return new List();
+ }
+
///
public override void Serialize(FRWriter writer)
{
diff --git a/FastReport.Base/Barcode/BarcodeDatamatrix.cs b/FastReport.Base/Barcode/BarcodeDatamatrix.cs
index 01f02067..0295af0a 100644
--- a/FastReport.Base/Barcode/BarcodeDatamatrix.cs
+++ b/FastReport.Base/Barcode/BarcodeDatamatrix.cs
@@ -397,6 +397,15 @@ private void Draw(byte[] data, int dataSize, DmParams dm)
private static void MakePadding(byte[] data, int position, int count)
{
+ // set to ascii mode
+ if ((count > 0) && (position > 0))
+ {
+ if (data[position - 1] != 254)
+ data[position] = 254;
+ position++;
+ count--;
+ }
+
//already in ascii mode
if (count <= 0)
return;
@@ -733,7 +742,7 @@ private static int C40OrTextEncodation(byte[] text, int textOffset, int textLeng
ptrIn = last0;
encPtr = last1;
}
- if (encPtr / 3 * 2 > dataLength - 2)
+ if (encPtr / 3 * 2 > dataLength - 1)
{
return -1;
}
@@ -744,8 +753,12 @@ private static int C40OrTextEncodation(byte[] text, int textOffset, int textLeng
data[dataOffset + ptrOut++] = (byte)(a / 256);
data[dataOffset + ptrOut++] = (byte)a;
}
- data[ptrOut++] = (byte)254;
- i = AsciiEncodation(text, ptrIn, textLength - ptrIn, data, ptrOut, dataLength - ptrOut);
+ i = 0;
+ if (textLength - ptrIn > 0)
+ {
+ data[ptrOut++] = (byte)254;
+ i = AsciiEncodation(text, ptrIn, textLength - ptrIn, data, ptrOut, dataLength - ptrOut);
+ }
if (i < 0)
return i;
return ptrOut + i;
diff --git a/FastReport.Base/Data/JsonConnection/JsonDataSourceConnection.cs b/FastReport.Base/Data/JsonConnection/JsonDataSourceConnection.cs
index 6601a670..985ef68d 100644
--- a/FastReport.Base/Data/JsonConnection/JsonDataSourceConnection.cs
+++ b/FastReport.Base/Data/JsonConnection/JsonDataSourceConnection.cs
@@ -28,6 +28,7 @@ public partial class JsonDataSourceConnection : DataConnectionBase
private JsonArray jsonInternal = null;
private JsonSchema jsonSchema = null;
private string jsonSchemaString = "";
+ private bool simpleStructure;
#endregion Private Fields
@@ -53,6 +54,14 @@ internal JsonSchema JsonSchema
}
}
+ internal bool SimpleStructure
+ {
+ get
+ {
+ return simpleStructure;
+ }
+ }
+
#endregion Internal Properties
#region Public Constructors
@@ -182,6 +191,7 @@ private void InitConnection()
private void InitConnection(bool rebuildSchema)
{
JsonDataSourceConnectionStringBuilder builder = new JsonDataSourceConnectionStringBuilder(ConnectionString);
+ simpleStructure = builder.SimpleStructure;
JsonBase obj = null;
string jsonText = builder.Json.Trim();
if (jsonText.Length > 0)
diff --git a/FastReport.Base/Data/JsonConnection/JsonDataSourceConnectionStringBuilder.cs b/FastReport.Base/Data/JsonConnection/JsonDataSourceConnectionStringBuilder.cs
index b5d83b51..53960dc1 100644
--- a/FastReport.Base/Data/JsonConnection/JsonDataSourceConnectionStringBuilder.cs
+++ b/FastReport.Base/Data/JsonConnection/JsonDataSourceConnectionStringBuilder.cs
@@ -67,6 +67,8 @@ public string JsonSchema
}
}
+
+
///
/// Gets or sets json url encoding
///
@@ -85,7 +87,102 @@ public string Encoding
}
}
- public Dictionary Headers { get; set; }
+ ///
+ /// Set or get headers of the connection string.
+ ///
+ ///
+ ///
+ /// Returns copy of dictionary. If you need to update values, set the dictionary again!
+ ///
+ public Dictionary Headers
+ {
+ get
+ {
+ var numberformat = CultureInfo.InvariantCulture.NumberFormat;
+ Dictionary headers = new Dictionary();
+ object result;
+ string header = string.Empty;
+ string[] splittedHeader;
+ int headerIteration = 0;
+ while (TryGetValue("Header" + headerIteration.ToString(numberformat), out result) && result != null)
+ {
+ header = (string)result;
+
+ if (!string.IsNullOrWhiteSpace(header))
+ {
+ splittedHeader = header.Split(':');
+
+ string headerKey = splittedHeader[0], headerVal = splittedHeader[1];
+
+ if (Regex.IsMatch(headerKey, @"^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)?$"))
+ {
+ var base64str = Convert.FromBase64String(headerKey);
+ headerKey = System.Text.Encoding.UTF8.GetString(base64str);
+ }
+
+ if (Regex.IsMatch(headerVal, @"^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)?$"))
+ {
+ var base64str = Convert.FromBase64String(headerVal);
+ headerVal = System.Text.Encoding.UTF8.GetString(base64str);
+ }
+
+ headers[headerKey] = headerVal;
+ }
+ headerIteration++;
+ }
+ return headers;
+ }
+ set
+ {
+ var numberformat = CultureInfo.InvariantCulture.NumberFormat;
+ int headerIteration = 0;
+
+ while (Remove("Header" + headerIteration.ToString(numberformat)))
+ {
+ headerIteration++;
+ }
+
+ if (value != null)
+ {
+ headerIteration = 0;
+ foreach (var header in value)
+ {
+ var headerKey = header.Key;
+ var headerVal = header.Value;
+ if (headerKey.Contains(":"))
+ {
+ headerKey = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(headerKey));
+ }
+
+ if (headerVal.Contains(":"))
+ {
+ headerVal = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(headerVal));
+ }
+
+ base["Header" + headerIteration.ToString(numberformat)] = headerKey + ":" + headerVal;
+ headerIteration++;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets simple structure value
+ ///
+ public bool SimpleStructure
+ {
+ get
+ {
+ object result;
+ if (TryGetValue("SimpleStructure", out result) && result != null)
+ return result.ToString().ToLower() == "true";
+ return false;
+ }
+ set
+ {
+ base["SimpleStructure"] = value ? "true" : "false";
+ }
+ }
@@ -99,7 +196,6 @@ public string Encoding
public JsonDataSourceConnectionStringBuilder()
{
ConnectionString = "";
- Headers = new Dictionary();
}
///
@@ -111,76 +207,8 @@ public JsonDataSourceConnectionStringBuilder(string connectionString)
: base()
{
ConnectionString = connectionString;
- Headers = new Dictionary();
- //while (ConnectionString.Contains("Header="))
- //{
- object result;
- string header = string.Empty;
- string[] splittedHeader;
- int headerIteration = 0;
- while (TryGetValue("Header" + headerIteration.ToString(CultureInfo.InvariantCulture.NumberFormat), out result) && result != null)
- {
- header = (string)result;
-
- if (!string.IsNullOrWhiteSpace(header))
- {
- splittedHeader = header.Split(':');
-
- string headerKey = splittedHeader[0], headerVal = splittedHeader[1];
-
- if (Regex.IsMatch(headerKey, @"^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)?$"))
- {
- var base64str = Convert.FromBase64String(headerKey);
- headerKey = System.Text.Encoding.UTF8.GetString(base64str);
- }
-
- if (Regex.IsMatch(headerVal, @"^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)?$"))
- {
- var base64str = Convert.FromBase64String(headerVal);
- headerVal = System.Text.Encoding.UTF8.GetString(base64str);
- }
-
- Headers.Add(headerKey, headerVal);
- //ConnectionString = ConnectionString.Replace(header, string.Empty);
- }
-
- headerIteration++;
- }
- //}
}
#endregion Public Constructors
-
- // escape / ; " :
- public override string ToString()
- {
- //TODO: do via stringbuilder
- //string connString = $"Json={Json};JsonSchema={JsonSchema};Encoding={Encoding}";
- StringBuilder builder = new StringBuilder();
- builder.Append("Json=").Append(Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Json)))
- .Append(";JsonSchema=").Append(Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(JsonSchema)))
- .Append(";Encoding=").Append(Encoding);
- //string connString = "Json=" + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Json))
- // + ";JsonSchema=" + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(JsonSchema)) + ";Encoding=" + Encoding;
- int headerIteration = 0;
- foreach (var header in Headers)
- {
- var headerKey = header.Key;
- var headerVal = header.Value;
- if (headerKey.Contains(";") || headerKey.Contains(":") || headerKey.Contains("\"") || headerKey.Contains("\'"))
- {
- headerKey = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(headerKey));
- }
-
- if (headerVal.Contains(";") || headerVal.Contains(":") || headerVal.Contains("\"") || headerVal.Contains("\'"))
- {
- headerVal = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(headerVal));
- }
-
- builder.Append(";Header").Append(headerIteration.ToString(CultureInfo.InvariantCulture.NumberFormat)).Append("=").Append(headerKey).Append(":").Append(headerVal);
- //connString += ";Header" + headerIteration + "=" + headerKey + ":" + headerVal;
- }
- return builder.ToString();
- }
}
}
\ No newline at end of file
diff --git a/FastReport.Base/Data/JsonConnection/JsonTableDataSource.cs b/FastReport.Base/Data/JsonConnection/JsonTableDataSource.cs
index bdf63806..40f9c8cc 100644
--- a/FastReport.Base/Data/JsonConnection/JsonTableDataSource.cs
+++ b/FastReport.Base/Data/JsonConnection/JsonTableDataSource.cs
@@ -1,8 +1,10 @@
using FastReport.Data.ElasticSearch;
using FastReport.Data.JsonConnection.JsonParser;
+using FastReport.Utils;
using System;
using System.Collections;
using System.Collections.Generic;
+using System.ComponentModel;
namespace FastReport.Data.JsonConnection
{
@@ -15,6 +17,8 @@ public class JsonTableDataSource : TableDataSource
private JsonArray _json;
private bool updateSchema;
+ private bool simpleStructure;
+ private string tableData;
#endregion Private Fields
@@ -23,6 +27,7 @@ public class JsonTableDataSource : TableDataSource
///
/// Gets or sets value for force update schema on init schema
///
+ [Browsable(false)]
public bool UpdateSchema
{
get
@@ -34,6 +39,41 @@ public bool UpdateSchema
updateSchema = value;
}
}
+ ///
+ /// Get or sets simplify mode for array types
+ ///
+ [Browsable(false)]
+ public bool SimpleStructure
+ {
+ get
+ {
+ return simpleStructure;
+ }
+
+ set
+ {
+ simpleStructure = value;
+ }
+ }
+
+ ///
+ [Browsable(false)]
+ public override string TableData
+ {
+ get
+ {
+ if (String.IsNullOrEmpty(tableData))
+ {
+ tableData = Json.ToString();
+ }
+ return tableData;
+ }
+
+ set
+ {
+ tableData = value;
+ }
+ }
#endregion Public Properties
@@ -45,7 +85,14 @@ internal JsonArray Json
{
if (_json == null)
{
- _json = GetJson(Parent, this) as JsonArray;
+ if (StoreData && !String.IsNullOrEmpty(tableData))
+ {
+ _json = JsonBase.FromString(tableData) as JsonArray;
+ }
+ else
+ {
+ _json = GetJson(Parent, this) as JsonArray;
+ }
if (_json == null)
_json = new JsonArray();
}
@@ -101,13 +148,14 @@ public override void InitializeComponent()
///
public override void InitSchema()
{
- if (Columns.Count == 0 || UpdateSchema)
+ if (Columns.Count == 0 || UpdateSchema && !StoreData)
{
+
if (Connection is JsonDataSourceConnection)
{
JsonDataSourceConnection con = Connection as JsonDataSourceConnection;
- InitSchema(this, con.JsonSchema);
+ InitSchema(this, con.JsonSchema, con.SimpleStructure);
}
}
UpdateSchema = false;
@@ -117,7 +165,8 @@ public override void InitSchema()
public override void LoadData(ArrayList rows)
{
Json = null;
- if ( rows != null)
+ // JSON is calculated property, no problem with null
+ if (rows != null && Json != null)
{
rows.Clear();
int count = Json.Count;
@@ -136,13 +185,25 @@ internal static object GetJsonBaseByColumn(Base parentColumn, Column column)
{
if (parentColumn is JsonTableDataSource)
{
- switch (column.PropName)
+ JsonTableDataSource jsonTableDataSource = parentColumn as JsonTableDataSource;
+ if (jsonTableDataSource.SimpleStructure)
{
- case "item":
- return (parentColumn as JsonTableDataSource).Json[(parentColumn as JsonTableDataSource).CurrentIndex];
+ if (!String.IsNullOrEmpty(column.PropName))
+ {
+ var obj = (parentColumn as JsonTableDataSource).Json[(parentColumn as JsonTableDataSource).CurrentIndex];
+ return (obj as JsonBase)[column.PropName];
+ }
+ }
+ else
+ {
+ switch (column.PropName)
+ {
+ case "item":
+ return (parentColumn as JsonTableDataSource).Json[(parentColumn as JsonTableDataSource).CurrentIndex];
+ }
+ JsonTableDataSource source = column as JsonTableDataSource;
+ return source.Json;
}
- JsonTableDataSource source = column as JsonTableDataSource;
- return source.Json;
}
if (parentColumn is Column && !String.IsNullOrEmpty(column.PropName))
{
@@ -175,7 +236,7 @@ internal static object GetValueByColumn(Base parentColumn, Column column)
return json;
}
- internal static void InitSchema(Column table, JsonSchema schema)
+ internal static void InitSchema(Column table, JsonSchema schema, bool simpleStructure)
{
List saveColumns = new List();
switch (schema.Type)
@@ -191,7 +252,7 @@ internal static void InitSchema(Column table, JsonSchema schema)
c.PropName = kv.Key;
c.DataType = kv.Value.DataType;
c = UpdateColumn(table, c, saveColumns);
- InitSchema(c, kv.Value);
+ InitSchema(c, kv.Value, simpleStructure);
}
else if (kv.Value.Type == "array")
{
@@ -201,7 +262,9 @@ internal static void InitSchema(Column table, JsonSchema schema)
c.PropName = kv.Key;
c.DataType = kv.Value.DataType;
c = UpdateColumn(table, c, saveColumns);
- InitSchema(c, kv.Value);
+
+ InitSchema(c, kv.Value, simpleStructure);
+
}
else
{
@@ -218,6 +281,26 @@ internal static void InitSchema(Column table, JsonSchema schema)
case "array":
JsonSchema items = schema.Items;
+
+ bool simpleArray = false;
+
+ if (table is JsonTableDataSource)
+ {
+ JsonTableDataSource jsonTableDataSource = table as JsonTableDataSource;
+ simpleArray = jsonTableDataSource.SimpleStructure =
+ simpleStructure & items.Type == "object";
+ }
+
+ if (simpleArray)
+ {
+ // remake schema in simplify mode
+ InitSchema(table, items, simpleStructure);
+ // and return, no need to clear column data
+ // in this case this method has no control to columns
+ return;
+ }
+
+
{
Column c = new Column();
c.Name = "index";
@@ -227,6 +310,8 @@ internal static void InitSchema(Column table, JsonSchema schema)
UpdateColumn(table, c, saveColumns);
}
+
+
{
Column c;
bool iSchema = false;
@@ -254,7 +339,7 @@ internal static void InitSchema(Column table, JsonSchema schema)
c = UpdateColumn(table, c, saveColumns);
if (iSchema)
- InitSchema(c, items);
+ InitSchema(c, items, simpleStructure);
}
{
@@ -265,6 +350,7 @@ internal static void InitSchema(Column table, JsonSchema schema)
c.DataType = typeof(JsonBase);
UpdateColumn(table, c, saveColumns);
}
+
break;
}
@@ -280,7 +366,7 @@ internal static void InitSchema(Column table, JsonSchema schema)
internal object GetJson(Base parentColumn, Column column)
{
- if(parentColumn is ESDataSourceConnection)
+ if (parentColumn is ESDataSourceConnection)
parentColumn = (parentColumn as ESDataSourceConnection).GetParentJTDSByName(column.Name);
if (parentColumn is JsonDataSourceConnection)
{
@@ -292,7 +378,19 @@ internal object GetJson(Base parentColumn, Column column)
if (parentColumn.Parent is ESDataSourceConnection)
parentColumn.Parent = (parentColumn.Parent as ESDataSourceConnection).GetParentJTDSByName(parentColumn.Name);
JsonTableDataSource source = parentColumn as JsonTableDataSource;
- return source.Json[source.CurrentRowNo] as object;
+
+ if (source.SimpleStructure)
+ {
+ object parentJson = source.Json[source.CurrentRowNo];
+ if (parentJson is JsonBase && !String.IsNullOrEmpty(column.PropName))
+ {
+ return (parentJson as JsonBase)[column.PropName];
+ }
+ }
+ else
+ {
+ return source.Json[source.CurrentRowNo] as object;
+ }
}
else if (parentColumn is Column)
{
@@ -353,5 +451,17 @@ private static Column UpdateColumn(Column table, Column c, List list)
}
#endregion Private Methods
+
+
+ ///
+ public override void Serialize(FRWriter writer)
+ {
+ base.Serialize(writer);
+
+ if (SimpleStructure)
+ {
+ writer.WriteBool("SimpleStructure", SimpleStructure);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/FastReport.Base/Data/TableDataSource.cs b/FastReport.Base/Data/TableDataSource.cs
index 86c969ab..5ab3d0f1 100644
--- a/FastReport.Base/Data/TableDataSource.cs
+++ b/FastReport.Base/Data/TableDataSource.cs
@@ -126,7 +126,7 @@ public bool StoreData
/// This property is for internal use only.
///
[Browsable(false)]
- public string TableData
+ public virtual string TableData
{
get
{
diff --git a/FastReport.Base/Export/Html/HTMLExportDraw.cs b/FastReport.Base/Export/Html/HTMLExportDraw.cs
index 15c65425..67126011 100644
--- a/FastReport.Base/Export/Html/HTMLExportDraw.cs
+++ b/FastReport.Base/Export/Html/HTMLExportDraw.cs
@@ -65,8 +65,10 @@ private string HTMLBorderWidthPx(BorderLine line)
float width;
if (line.Style == LineStyle.Double)
width = line.Width * 3 * Zoom;
- else
+ else if (layers)
width = line.Width * Zoom;
+ else
+ width = line.Width;
return ExportUtils.FloatToString(width) + "px;";
}
diff --git a/FastReport.Base/Export/Html/HTMLExportLayers.cs b/FastReport.Base/Export/Html/HTMLExportLayers.cs
index c9cfdddd..7423f12e 100644
--- a/FastReport.Base/Export/Html/HTMLExportLayers.cs
+++ b/FastReport.Base/Export/Html/HTMLExportLayers.cs
@@ -565,19 +565,19 @@ private string GetLayerPicture(ReportComponentBase obj, out float Width, out flo
BorderLines oldLines = obj.Border.Lines;
obj.Border.Lines = BorderLines.None;
- obj.Draw(new FRPaintEventArgs(g, Zoom + zoom - 1, Zoom + zoom - 1, Report.GraphicCache));
+ obj.Draw(new FRPaintEventArgs(g, Zoom * zoom, Zoom * zoom, Report.GraphicCache));
obj.Border.Lines = oldLines;
}
if(Width > 0 && Height > 0)
using (Bitmap b = new Bitmap(
- (int)(Math.Abs(Math.Round(Width * Zoom * zoom))),
- (int)(Math.Abs(Math.Round(Height * Zoom * zoom)))
+ (int)(Math.Abs(Math.Round(Width * Zoom))),
+ (int)(Math.Abs(Math.Round(Height * Zoom)))
))
{
using (Graphics gr = Graphics.FromImage(b))
{
gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
- gr.DrawImage(image, 0, 0, (int)Width * Zoom * zoom, (int)Height * Zoom * zoom);
+ gr.DrawImage(image, 0, 0, (int)Width * Zoom, (int)Height * Zoom);
}
if (FPictureFormat == System.Drawing.Imaging.ImageFormat.Jpeg)
@@ -612,6 +612,7 @@ private string GetLayerPicture(ReportComponentBase obj, out float Width, out flo
}
}
#else
+
hash = Crypter.ComputeHash(PictureStream);
PictureStream.Position = 0;
#endif
diff --git a/FastReport.Base/Import/DevExpress/DevExpressImport.cs b/FastReport.Base/Import/DevExpress/DevExpressImport.cs
index 46a84d01..1a42c0f2 100644
--- a/FastReport.Base/Import/DevExpress/DevExpressImport.cs
+++ b/FastReport.Base/Import/DevExpress/DevExpressImport.cs
@@ -1011,11 +1011,24 @@ private void LoadReport()
#region Public Methods
+ ///
public override void LoadReport(Report report, string filename)
+ {
+ using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
+ {
+ LoadReport(report, fs);
+ }
+ }
+
+ ///
+ public override void LoadReport(Report report, Stream content)
{
Report = report;
Report.Clear();
- devText = File.ReadAllText(filename);
+ using(var sr = new StreamReader(content))
+ {
+ devText = sr.ReadToEnd();
+ }
try
{
devDoc = new System.Xml.XmlDocument();
diff --git a/FastReport.Base/Import/ImportBase.cs b/FastReport.Base/Import/ImportBase.cs
index 4c1467e5..f9aef857 100644
--- a/FastReport.Base/Import/ImportBase.cs
+++ b/FastReport.Base/Import/ImportBase.cs
@@ -1,3 +1,5 @@
+using System.IO;
+
namespace FastReport.Import
{
///
@@ -57,6 +59,16 @@ public virtual void LoadReport(Report report, string filename)
report.Clear();
}
+ ///
+ /// Loads the specified file into specified report from stream.
+ ///
+ /// Report object
+ /// File stream
+ public virtual void LoadReport(Report report, Stream content)
+ {
+ report.Clear();
+ }
+
#endregion // Public Methods
}
}
diff --git a/FastReport.Base/Import/ListAndLabel/ListAndLabelImport.cs b/FastReport.Base/Import/ListAndLabel/ListAndLabelImport.cs
index a2172f2d..29229eb4 100644
--- a/FastReport.Base/Import/ListAndLabel/ListAndLabelImport.cs
+++ b/FastReport.Base/Import/ListAndLabel/ListAndLabelImport.cs
@@ -413,7 +413,19 @@ private void LoadReport()
///
public override void LoadReport(Report report, string filename)
{
- textLL = File.ReadAllText(filename);
+ using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
+ {
+ LoadReport(report, fs);
+ }
+ }
+
+ ///
+ public override void LoadReport(Report report, Stream content)
+ {
+ using(var sr = new StreamReader(content))
+ {
+ textLL = sr.ReadToEnd();
+ }
isListAndLabelReport = CheckIsListAndLabelReport();
if (isListAndLabelReport)
{
diff --git a/FastReport.Base/Import/RDL/RDLImport.cs b/FastReport.Base/Import/RDL/RDLImport.cs
index f2c29ac2..d162809f 100644
--- a/FastReport.Base/Import/RDL/RDLImport.cs
+++ b/FastReport.Base/Import/RDL/RDLImport.cs
@@ -926,11 +926,19 @@ private void LoadReport(XmlNode reportNode)
public override void LoadReport(Report report, string filename)
{
this.filename = filename;
+ using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
+ {
+ LoadReport(report, fs);
+ }
+ }
+ ///
+ public override void LoadReport(Report report, Stream content)
+ {
Report = report;
Report.Clear();
- XmlDocument doc = new XmlDocument();
- doc.Load(filename);
- reportNode = doc.LastChild;
+ XmlDocument document = new XmlDocument();
+ document.Load(content);
+ reportNode = document.LastChild;
defaultFontFamily = "";
page = null;
LoadReport(reportNode);
diff --git a/FastReport.Base/PictureObjectBase.cs b/FastReport.Base/PictureObjectBase.cs
index 2993530d..7c57e471 100644
--- a/FastReport.Base/PictureObjectBase.cs
+++ b/FastReport.Base/PictureObjectBase.cs
@@ -820,7 +820,7 @@ protected void UpdateAutoSize()
{
if (ImageWidth == 0 || ImageHeight == 0)
{
- if (IsRunning)
+ if (IsRunning && !IsPrinting)
{
Width = 0;
Height = 0;
diff --git a/FastReport.Base/ReportComponentBase.cs b/FastReport.Base/ReportComponentBase.cs
index fbf864ea..b55624a2 100644
--- a/FastReport.Base/ReportComponentBase.cs
+++ b/FastReport.Base/ReportComponentBase.cs
@@ -792,6 +792,29 @@ public virtual bool IsVisible(FRPaintEventArgs e)
return e.Graphics.IsVisible(objRect);
}
+ ///
+ /// Validate this object.
+ ///
+ /// List of errors
+ public virtual List Validate()
+ {
+ List listError = new List();
+
+ if (IsIntersectingWithOtherObject && !(Parent is ReportComponentBase && !Validator.RectContainInOtherRect((Parent as ReportComponentBase).AbsBounds, this.AbsBounds)))
+ listError.Add(new ValidationError(Name, ValidationError.ErrorLevel.Warning, Res.Get("Messages,Validator,IntersectedObjects"), this));
+
+ if (Height <= 0 || Width <= 0)
+ listError.Add(new ValidationError(Name, ValidationError.ErrorLevel.Error, Res.Get("Messages,Validator,IncorrectSize"), this));
+
+ if (Name == "")
+ listError.Add(new ValidationError(Name, ValidationError.ErrorLevel.Error, Res.Get("Messages,Validator,UnnamedObject"), this));
+
+ if (Parent is ReportComponentBase && !Validator.RectContainInOtherRect((Parent as ReportComponentBase).AbsBounds, this.AbsBounds))
+ listError.Add(new ValidationError(Name, ValidationError.ErrorLevel.Error, Res.Get("Messages,Validator,OutOfBounds"), this));
+
+ return listError;
+ }
+
///
public override void Serialize(FRWriter writer)
{
diff --git a/FastReport.Base/Utils/Validator.cs b/FastReport.Base/Utils/Validator.cs
index c1f978a3..d243003d 100644
--- a/FastReport.Base/Utils/Validator.cs
+++ b/FastReport.Base/Utils/Validator.cs
@@ -1,8 +1,33 @@
using System;
+using System.Collections.Generic;
using System.Drawing;
+using System.Linq;
namespace FastReport.Utils
{
+
+ public struct ValidationError
+ {
+ public enum ErrorLevel
+ {
+ Warning,
+ Error
+ }
+
+ public string Name;
+ public ErrorLevel Level;
+ public string Message;
+ public ReportComponentBase Object;
+
+ public ValidationError(string name, ErrorLevel level, string message, ReportComponentBase obj)
+ {
+ this.Name = name;
+ this.Level = level;
+ this.Message = message;
+ this.Object = obj;
+ }
+ }
+
///
/// Contains methods used for validation of report.
///
@@ -43,9 +68,57 @@ static public bool ValidateIntersectionAllObjects(BandBase band)
return result;
}
+ ///
+ /// Check child rectangle on contains in parent rectangle.
+ ///
+ ///
+ ///
+ ///
+ static public bool RectContainInOtherRect(RectangleF parent, RectangleF child)
+ {
+ return parent.Contains(GetReducedRect(child));
+ }
+
private static RectangleF GetReducedRect(RectangleF rect)
{
return new RectangleF(rect.X + 0.01f, rect.Y + 0.01f, rect.Width - 0.02f, rect.Height - 0.02f);
}
+
+ static public List ValidateReport(Report report)
+ {
+ if (report == null)
+ return null;
+ List listError = new List();
+
+ foreach (PageBase page in report.Pages)
+ {
+ foreach (Base c in page.AllObjects)
+ {
+ if (c is ReportComponentBase)
+ listError.AddRange((c as ReportComponentBase).Validate());
+
+ if (c is BandBase)
+ ValidateIntersectionAllObjects(c as BandBase);
+ }
+ }
+
+ bool duplicateName;
+ for (int i = 0; i < report.AllObjects.Count - 1; i++)
+ {
+ duplicateName = false;
+ for (int j = i + 1; j < report.AllObjects.Count; j++)
+ {
+ if (report.AllObjects[j] is ReportComponentBase && report.AllObjects[i].Name == report.AllObjects[j].Name)
+ {
+ listError.Add(new ValidationError(report.AllObjects[j].Name, ValidationError.ErrorLevel.Error, Res.Get("Messages,Validator,DuplicateName"), (ReportComponentBase)report.AllObjects[j]));
+ duplicateName = true;
+ }
+ }
+ if(report.AllObjects[i] is ReportComponentBase && duplicateName)
+ listError.Add(new ValidationError(report.AllObjects[i].Name, ValidationError.ErrorLevel.Error, Res.Get("Messages,Validator,DuplicateName"), (ReportComponentBase)report.AllObjects[i]));
+ }
+
+ return listError.Distinct().ToList();
+ }
}
}
\ No newline at end of file
diff --git a/FastReport/Resources/en.xml b/FastReport/Resources/en.xml
index 9c343672..38b238f4 100644
--- a/FastReport/Resources/en.xml
+++ b/FastReport/Resources/en.xml
@@ -69,6 +69,13 @@
+
+
+
+
+
+
+
@@ -491,6 +498,11 @@
+
+
+
+
+
@@ -2276,6 +2288,7 @@
+
diff --git a/Localization/Russian.frl b/Localization/Russian.frl
index c7def221..9cc95798 100644
--- a/Localization/Russian.frl
+++ b/Localization/Russian.frl
@@ -69,6 +69,13 @@
+
+
+
+
+
+
+
@@ -473,9 +480,9 @@
-
-
-
+
+
+
@@ -486,6 +493,11 @@
+
+
+
+
+
@@ -2062,6 +2074,7 @@
+