using System; using System.ComponentModel; using FastReport.Utils; using FastReport.Format; using System.Windows.Forms; using System.Drawing.Design; namespace FastReport { /// /// Specifies how to display the duplicate values. /// public enum Duplicates { /// /// The TextObject can show duplicate values. /// Show, /// /// The TextObject with duplicate value will be hidden. /// Hide, /// /// The TextObject with duplicate value will be shown but with no text. /// Clear, /// /// Several TextObject objects with the same value will be merged into one TextObject object. /// Merge } /// /// Specifies how the report engine processes the text objects. /// public enum ProcessAt { /// /// Specifies the default process mode. The text object is processed just-in-time. /// Default, /// /// Specifies that the text object must be processed when the entire report is finished. This mode /// can be used to print grand total value (which is normally calculated at the end of report) in the /// report title band. /// ReportFinished, /// /// Specifies that the text object must be processed when the entire report page is finished. This mode /// can be used if the report template consists of several report pages. /// ReportPageFinished, /// /// Specifies that the text object must be processed when any report page is finished. This mode /// can be used to print the page total (which is normally calculated at the page footer) in the /// page header band. /// PageFinished, /// /// Specifies that the text object must be processed when the column is finished. This mode /// can be used to print the column total (which is normally calculated at the column footer) in the /// column header band. /// ColumnFinished, /// /// Specifies that the text object must be processed when the data block is finished. This mode can be /// used to print a total value in the data header (which is normally available /// in the data footer only). /// DataFinished, /// /// Specifies that the text object must be processed when the group is finished. This mode can be /// used to print a total value in the group header (which is normally available /// in the group footer only). /// GroupFinished, /// /// Specifies that the text object is processed manually when you call the Engine.ProcessObject /// method in the report script. /// Custom } /// /// Base class for text objects such as and . /// /// /// This class implements common functionality of the text objects. /// public partial class TextObjectBase : BreakableComponent { #region Fields private string text; private object value; private bool allowExpressions; private string brackets; private Padding padding; private bool hideZeros; private string hideValue; private string nullValue; private FormatCollection formats; private ProcessAt processAt; private Duplicates duplicates; private bool editable; #endregion #region Properties /// /// Gets or sets a value indicating that the object's text may contain expressions. /// [DefaultValue(true)] [Category("Data")] public bool AllowExpressions { get { return allowExpressions; } set { allowExpressions = value; } } /// /// Gets or sets the symbols that will be used to find expressions in the object's text. /// /// /// The default property value is "[,]". As you can see, the open and close symbols are /// separated by the comma. You may use another symbols, for example: "<,>" or "<%,%>". /// You should use different open and close symbols. /// [Category("Data")] public string Brackets { get { return brackets; } set { brackets = value; } } /// /// Gets or sets the object's text. /// /// /// Text may contain expressions and data items, for example: "Today is [Date]". /// When report is running, all expressions are calculated and replaced with actual /// values, so the text would be "Today is 01.01.2008". /// [Category("Data")] public virtual string Text { get { return text; } set { text = value; } } /// /// Gets or sets padding within the text object. /// [Category("Layout")] public Padding Padding { get { return padding; } set { padding = value; } } /// /// Gets or sets a value indicating that zero values must be hidden. /// [Category("Behavior")] [DefaultValue(false)] public bool HideZeros { get { return hideZeros; } set { hideZeros = value; } } /// /// Gets or sets a value that will be hidden. /// /// /// Use this property to specify a value that you would like to hide. For example, specify "0" /// if you want to hide zero values, or use property to do this. /// You also may use this property to hide default DateTime values (such as 1/1/1900). /// In this case you need to specify a string containing both date and time, for example: /// "1/1/1900 0:00:00". /// /// FastReport uses the ToString conversion to compare the expression value with this property. /// This conversion depends on regional settings selected in the Control Panel, so be aware of this /// if you going to distribute your report worldwide. /// /// [Category("Behavior")] public string HideValue { get { return hideValue; } set { hideValue = value; } } /// /// Gets or sets a string that will be displayed instead of a null value. /// [Category("Behavior")] public string NullValue { get { return nullValue; } set { nullValue = value; } } /// /// Gets or sets the formatter that will be used to format data in the Text object. /// /// /// The default formatter does nothing, i.e. it shows expression values with no formatting. /// To set another formatting, create a new formatter and assign it to this property. /// If there are several expressions in the text, use the property /// to format each expression value. /// /// This example shows how to set currency formatter. /// /// TextObject text1; /// text1.Format = new CurrencyFormat(); /// /// [Category("Data")] [Editor("FastReport.TypeEditors.FormatEditor, FastReport", typeof(UITypeEditor))] public FormatBase Format { get { return formats.Count == 0 ? new GeneralFormat() : formats[0]; } set { if (value == null) value = new GeneralFormat(); if (formats.Count == 0) formats.Add(value); else formats[0] = value; } } /// /// Gets or sets a value that specifies how the report engine processes this text object. /// /// /// Use this property to perform such task as "print a total value in the group header". Normally, /// all total values are calculated in the footers (for example, in a group footer). If you try to print /// a total value in the group header, you will get 0. If you set this property to /// ProcessAt.DataFinished, FastReport will do the following: /// /// /// print the object (with wrong value); /// /// /// print all related data rows; /// /// /// calculate the correct object's value and replace old (wrong) value with the new one. /// /// /// /// This option will not work if you set the to true. /// /// [Category("Behavior")] [DefaultValue(ProcessAt.Default)] public ProcessAt ProcessAt { get { return processAt; } set { processAt = value; } } /// /// Gets the collection of formatters. /// /// /// This property is used to set format for each expression contained in the text. /// For example, if the TextObject contains two expressions: /// Today is [Date]; Page [PageN] /// you can use the following code to format these expressions separately: /// /// text1.Formats.Clear(); /// text1.Formats.Add(new DateFormat()); /// text1.Formats.Add(new NumberFormat()); /// /// [Browsable(false)] public FormatCollection Formats { get { return formats; } } /// /// Gets or sets a value that determines how to display duplicate values. /// [DefaultValue(Duplicates.Show)] [Category("Behavior")] public Duplicates Duplicates { get { return duplicates; } set { duplicates = value; } } /// /// Gets a value of expression contained in the object's text. /// [Browsable(false)] public object Value { get { return value; } } /// /// Gets or sets editable for pdf export /// [Category("Behavior")] [DefaultValue(false)] public bool Editable { get { return editable; } set { editable = value; } } #endregion #region Protected Methods /// protected override void DeserializeSubItems(FRReader reader) { if (String.Compare(reader.ItemName, "Formats", true) == 0) reader.Read(Formats); else base.DeserializeSubItems(reader); } #endregion #region Public Methods /// public override void Assign(Base source) { base.Assign(source); TextObjectBase src = source as TextObjectBase; Text = src.Text; Padding = src.Padding; AllowExpressions = src.AllowExpressions; Brackets = src.Brackets; HideZeros = src.HideZeros; HideValue = src.HideValue; NullValue = src.NullValue; ProcessAt = src.ProcessAt; Formats.Assign(src.Formats); Duplicates = src.Duplicates; Editable = src.Editable; } /// public override void Serialize(FRWriter writer) { TextObjectBase c = writer.DiffObject as TextObjectBase; base.Serialize(writer); if (Text != c.Text) writer.WriteStr("Text", Text); if (Padding != c.Padding) writer.WriteValue("Padding", Padding); if (writer.SerializeTo != SerializeTo.Preview) { if (AllowExpressions != c.AllowExpressions) writer.WriteBool("AllowExpressions", AllowExpressions); if (Brackets != c.Brackets) writer.WriteStr("Brackets", Brackets); if (HideZeros != c.HideZeros) writer.WriteBool("HideZeros", HideZeros); if (HideValue != c.HideValue) writer.WriteStr("HideValue", HideValue); if (NullValue != c.NullValue) writer.WriteStr("NullValue", NullValue); if (ProcessAt != c.ProcessAt) writer.WriteValue("ProcessAt", ProcessAt); if (Duplicates != c.Duplicates) writer.WriteValue("Duplicates", Duplicates); } if (Editable) writer.WriteBool("Editable", Editable); if (Formats.Count > 1) writer.Write(Formats); else Format.Serialize(writer, "Format.", c.Format); } /// public override void ExtractMacros() { Text = ExtractDefaultMacros(Text); } internal void SetValue(object value) { this.value = value; } internal string GetTextWithBrackets(string text) { string[] brackets = Brackets.Split(','); return brackets[0] + text + brackets[1]; } internal string GetTextWithoutBrackets(string text) { string[] brackets = Brackets.Split(','); if (text.StartsWith(brackets[0])) text = text.Remove(0, brackets[0].Length); if (text.EndsWith(brackets[1])) text = text.Remove(text.Length - brackets[1].Length); return text; } internal string FormatValue(object value) { return FormatValue(value, 0); } internal string FormatValue(object value, int formatIndex) { this.value = value; string formattedValue = ""; if (value == null || value is DBNull) { formattedValue = NullValue; } else { if (formatIndex < Formats.Count) formattedValue = Formats[formatIndex].FormatValue(value); else formattedValue = Format.FormatValue(value); if (!String.IsNullOrEmpty(HideValue)) { if (value.ToString() == HideValue) formattedValue = ""; } if (HideZeros) { Variant v = new Variant(value); if ((v.IsNumeric && v == 0) || (v.IsDate && v.ToDateTime() == DateTime.MinValue)) formattedValue = ""; } } return formattedValue; } internal string CalcAndFormatExpression(string expression, int expressionIndex) { try { return FormatValue(Report.Calc(expression), expressionIndex); } catch (Exception e) { throw new Exception(Name + ": " + Res.Get("Messages,ErrorInExpression") + ": " + expression, e.InnerException == null ? e : e.InnerException); } } /// /// Returns the text to display. /// /// The text to display. /// This method is used to display simplified DB field names in the designer. In runtime, it returns the Text property value. public virtual string GetDisplayText() { return Text; } #endregion /// /// Initializes a new instance of the class with default settings. /// public TextObjectBase() { allowExpressions = true; brackets = "[,]"; padding = new Padding(2, 0, 2, 0); hideValue = ""; nullValue = ""; text = ""; formats = new FormatCollection(); formats.Add(new GeneralFormat()); } } }