I am using the QuestPDF library and MicroCharts to generate a pdf with charts.
It is happening to me that when generating the first bar graph, it does it correctly. However, if I keep generating more reports, the graph starts to look different.
Does anyone know why this could happen?
I hope you can help me.
I leave you some pictures so you understand what is happening to me:
First Report
Second report
third report
I leave the part of my code where I generate the Bar Chart:
List<ChartEntry> totalTransactionsByMonthsEntries = new List<ChartEntry> { };
List<string> randomColors = new List<string> { "#5AA454", "#A10A28", "#C7B42C", "#AAAAAA", "#80DFFF", "#FF80DF", "#008000", "#4D4DFF", "#333333", "#B84DFF", "#FFAD33", "#FF1A8C" };
var countBarColors = 0;
foreach (var item in paymentEvolutionExportDetail.TotalTransactionsByMonths)
{
totalTransactionsByMonthsEntries.Add(new ChartEntry(item.Transactions)
{
Label = item.Month,
ValueLabel = item.Transactions.ToString(),
Color = SKColor.Parse(randomColors[countBarColors]),
ValueLabelColor = SKColors.Black
});
countBarColors++;
}
var totalTransactionsByMonthsChart = new BarChart
{
Entries = totalTransactionsByMonthsEntries,
LabelOrientation = Orientation.Horizontal,
ValueLabelOrientation = Orientation.Horizontal,
IsAnimated = false,
LabelTextSize = 8,
Margin = 10
};
return totalTransactionsByMonthsChart;
And this is the part of the PDF, where I add the chart to my document:
grid.Item(2)
.PaddingLeft(-10)
.PaddingTop(-150)
.Width(270)
.Border(0.5f)
.BorderTop(0)
.BorderColor("#A5A5A5")
.Background("#FFFFFF")
.Height(200)
.Canvas((canvas, size) =>
{
barChart.DrawContent(canvas, 270, 200);
});
I tried giving the maximum value to the chart, but this gives me the same result as shown in the images.
var maxTransactionValue = paymentEvolutionExportDetail.TotalTransactionsByMonths.Select(x => x.Transactions).Max();
totalTransactionsByMonthsChart.MaxValue = maxTransactionValue;
Finally, I solved this problem by adding the bar chart generation to the PDF report generation:
grid.Item(2)
.PaddingLeft(-10)
.PaddingTop(-150)
.Width(270)
.Border(0.5f)
.BorderTop(0)
.BorderColor("#A5A5A5")
.Background("#FFFFFF")
.Height(200)
.Canvas((canvas, size) =>
{
var barChart = new BarChart
{
Entries = barChartEntries,
LabelOrientation = Orientation.Horizontal,
ValueLabelOrientation = Orientation.Horizontal,
IsAnimated = false,
LabelTextSize = 8,
Margin = 10
};
barChart.DrawContent(canvas, 270, 200);
});
Related
I want to add multiple texts on the connector line as per the image below. I am using c# code to automate the process. Below is my code which I have used. It is not giving the exact output as I had expected. Any help in this regard would be highly appreciated.
Visio.Shape vsoLastShape = visioPage.Shapes.get_ItemFromID(lastshapeID);
vsoLastShape.ConvertToGroup();
Visio.Selection vsoSelections = app.ActiveWindow.Selection;
vsoSelections.Select(vsoLastShape, (short)VisSelectArgs.visSelect);
Visio.Shape vsoGroupShape = vsoSelections.Group();
vsoGroupShape.Text = "Testing 12";
vsoGroupShape.TextStyle.PadLeft(10);
Whatever method (manual, C#, VBA or whatevber) you use, one shape can only contain one text. If you want to add more than one text then you need to convert the shape into a grouped shape. Then you can add a shape to the group and set that sub-shape's text to what you want.
Shape .Characters object used in conjunction with .Text allows for some flexibility.
private string nl = Environment.NewLine;
public void MultiText() {
try {
// using = System.Windows.Forms;
// using Vis = Microsoft.Office.Interop.Visio;
Vis.Application app = Globals.ThisAddIn.Application; // or launch Visio
Vis.Document vDoc = app.Documents.Add(""); // new blank document
Vis.Shape c1 = app.ActivePage.DrawOval(1, 1, 1.5, 1.5);
Vis.Shape s1 = app.ActivePage.DrawLine(1.5, 1.25, 4, 1.25);
s1.Text = $"Shape1{nl}Line2";
Vis.Shape c2 = app.ActivePage.DrawOval(4, 1, 4.5, 1.5);
Vis.Shape c3 = app.ActivePage.DrawOval(1, 3, 1.5, 3.5);
Vis.Shape s2 = app.ActivePage.DrawLine(1.5, 3.25, 4, 3.25);
s2.Text = $"Shape2";
Vis.Shape c4 = app.ActivePage.DrawOval(4, 3, 4.5, 3.5);
app.ActiveWindow.CenterViewOnShape(c4, Vis.VisCenterViewFlags.visCenterViewDefault);
app.ActiveWindow.Zoom = 1.2;
app.ActiveWindow.Selection.DeselectAll();
app.DoCmd((short)VisUICmds.visCmdDeselectAll);
System.Windows.Forms.MessageBox.Show($"2 Shapes with text.", "Continue...");
// reset the Text on Shape #2 and define 2 separate ranges
s2.Text = "";
// alocate a range
Characters range1 = s2.Characters;
range1.Begin = 0;
range1.End = 3;
range1.Text = "Name";
// alocate another
Characters range2 = s2.Characters;
range2.Begin = 4;
//range2.End = 7;
range2.Text = $"{Environment.NewLine}Type";
MessageBox.Show($"Now change Font Size", "Continue...");
// change font size or any of numerous properties
range1.CharProps[(short)Vis.VisCellIndices.visCharacterSize] = 16;
range2.CharProps[(short)Vis.VisCellIndices.visCharacterSize] = 8;
//range2.CharProps[(short)Vis.VisCellIndices.visCharacterStrikethru] = 1; // 1-true 0-false
MessageBox.Show($"Big Name!{nl}little Type.", "OK to continue");
} catch (Exception ex) {
ta.LogIt($"Err {ex.Message} Trace {ex.StackTrace}");
}
}
You may want to check this post and used the uploaded stencil. (Requires registration to see and download the attachment):
http://visguy.com/vgforum/index.php?topic=6318.msg25957#msg25957
I need to write AutoCAD plugin to display the area of the object.
Below is my code.
It works fine, but test is static. I need to keep tracking the area of the circle cir.Area.ToString();.
Currently, If I change the size of the circle latter on, the text does not change anymore.
For example, the area of my circle is 10. I run code, it displays 10. But if I change the radius of circle, the text remains 10.
How can I make it working.
[CommandMethod("displayarea")]
public static void Displayarea()
{
var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var filter = new SelectionFilter(new[] { new TypedValue(0, "Circle") });
var selection = ed.GetSelection(filter);
if (selection.Status != PromptStatus.OK)
return;
using (var tr = db.TransactionManager.StartTransaction())
{
var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
foreach (var id in selection.Value.GetObjectIds())
{
var ids = new ObjectIdCollection(new[] { id });
Circle cir = (Circle)tr.GetObject(id, OpenMode.ForRead) as Circle;
var _centerPosition = cir.Center;
using (DBText acText = new DBText())
{
acText.Position = _centerPosition;
acText.TextString = cir.Area.ToString();
acText.Height = 0.5;
curSpace.AppendEntity(acText);
tr.AddNewlyCreatedDBObject(acText, true);
}
}
tr.Commit();
}
}
Also you can use oEntity.Modified += OEntity_Modified;
Find this: Find which properties changed on modified event
You need to use fields.
Find this:
https://www.keanw.com/2007/07/accessing-the-a.html
It works by replacing
cir.Area.ToString();
to
string circarea = "%<\\AcObjProp Object(%<\\_ObjId "
+ CircleId
+ ">%).Area \\f \"%lu2\">%";
I am working with the opensource library LiveCharts in a wpf usercontrol.
All of my visualizations are working as intended except for my boxplots. For some reason the color of the legend on my boxplots doesn´t match the actual series.
In bare bones test app it looks like this.
Here is how i set up the chart and populate it.
public MainWindow()
{
chart1 = new Chart();
var testValues = new List<KeyValuePair<string, List<double>>>();
testValues.Add(new KeyValuePair<string, List<double>>("test", new List<double>() { 40, 30, 20, 10, 500 }));
testValues.Add(new KeyValuePair<string, List<double>>("tust", new List<double>() { 80, 10, 90, 30, 50 }));
chart1.AddBoxplotSeries(testValues, "titel");
}
public void AddBoxplotSeries(List<KeyValuePair<string, List<double>>> data, string title)
{
CartesianVisibility = Visibility.Visible;
ChartValues<OhlcPoint> values = new ChartValues<OhlcPoint>();
string[] labels = new string[data.Count];
//ChartValues<OhlcPoint> values = new ChartValues<OhlcPoint>();
foreach (var item in data)
{
double[] ohlc = new double[4];
ohlc[0] = item.Value.LowerQuartile();
ohlc[1] = item.Value.Maximum();
ohlc[2] = item.Value.Minimum();
ohlc[3] = item.Value.UpperQuartile();
labels[data.IndexOf(item)] = data[data.IndexOf(item)].Key;
values.Add(new OhlcPoint( ohlc[0], ohlc[1], ohlc[2], ohlc[3] ));
}
CartesianSeries.Add(new CandleSeries()
{
Values = values,
Title = title
});
XAxisLabels = labels;
LabelFormatter = value => value.ToString("N");
}
Am i doing something wrong or is this a bug ?
i have added a table with two rows and two columns and set border to all cells. but it shows the border only for first column
Sample code is shown below
var tableestdet = new Table
{
ColumnWidths = "120,120",
Margin = new MarginInfo { Top = 40, Left = 10 },
DefaultCellBorder = new BorderInfo((int)BorderSide.All, 1F),
};
tableestdet.DefaultCellTextInfo = new TextInfo { Alignment = AlignmentType.Center };
var estdet1 = tableestdet.Rows.Add();
estdet1.DefaultRowCellPadding = new MarginInfo { Top = 5, Bottom = 5 };
var req=estdet1.Cells.Add("Requested By:");
var estde=estdet1.Cells.Add("Entered By:");
var estdet2 = tableestdet.Rows.Add();
estdet2.DefaultCellTextInfo = new TextInfo
{
FontSize = 8,
Alignment = AlignmentType.Center
};
estdet2.DefaultRowCellPadding = new MarginInfo { Top = 5, Bottom = 5 };
estdet2.Cells.Add(Requestedby);
estdet2.Cells.Add(CustomerName);
sec1.Paragraphs.Add(tableestdet);
We have noticed that you are working with an outdated version of the API so please upgrade to Aspose.PDF for .NET 19.2 which is latest available version of the API as it includes more features and bug fixes. You may use below code snippet to add a table on page of PDF document, while setting borders for all cells.
// Load source PDF document
Aspose.Pdf.Document document = new Aspose.Pdf.Document();
// Add a page to the document
Page page = document.Pages.Add();
// Initializes a new instance of the Table
Aspose.Pdf.Table table = new Aspose.Pdf.Table();
// Set the table border color as LightGray
table.Border = new Aspose.Pdf.BorderInfo(Aspose.Pdf.BorderSide.All, .5f, Aspose.Pdf.Color.FromRgb(System.Drawing.Color.LightGray));
// Set the border for table cells
table.DefaultCellBorder = new Aspose.Pdf.BorderInfo(Aspose.Pdf.BorderSide.All, .5f, Aspose.Pdf.Color.FromRgb(System.Drawing.Color.LightGray));
// Create a loop to add 10 rows
for (int row_count = 1; row_count <= 10; row_count++)
{
// Add row to table
Aspose.Pdf.Row row = table.Rows.Add();
// Add table cells
row.Cells.Add("Column (" + row_count + ", 1)");
row.Cells.Add("Column (" + row_count + ", 2)");
}
// Add table object to first page of input document
page.Paragraphs.Add(table);
// Save updated document containing table object
document.Save(dataDir + "Table_19.2.pdf");
Generated PDF document has been attached for your kind reference Table19.2.pdf. Please feel free to let us know if you need any further assistance.
PS: I work with Aspose as Developer Evangelist.
I have a book library and I want to print library labels for them. When you select books from GridControl and click Print Labels button, the program creates labels on a pdf file like this:
private void btnQRPrintLabels_Click(object sender, EventArgs e)
{
// These are books' ids. Normally, these are retrieved from GridControl element.
var books_ids = new List<int>() {1, 2, 5, 6, 7, 12};
// I don't use PanelControl. But in the future, maybe I can use it later.
CreateLabels(books_ids, panelControl1);
}
And here is the contents of CreateLabels method:
public void CreateLabels(List<int> books_ids, PanelControl p)
{
var doc = new Document(PageSize.A4, 10, 10, 10, 10);
var m = new SaveFileDialog
{
Filter = #"PDF File Format|*.pdf",
FileName = "Labels.pdf"
};
if (m.ShowDialog() != DialogResult.OK) return;
var file = new FileStream(m.FileName, FileMode.Create);
wr = PdfWriter.GetInstance(doc, file);
doc.Open();
cb = wr.DirectContent;
wr.PageEvent = this;
// Labels are created from this method.
Labels(doc, books_ids);
doc.Close();
}
Finally, the contents of Labels method:
protected void Labels(Document doc, List<int> books_ids)
{
var i = 1;
foreach (var book_id in books_ids)
{
var alignment = (i % 2 != 0) ? Element.ALIGN_LEFT : Element.ALIGN_RIGHT;
// Book's informations are retrieved from Linq Connect Model.
var _connection = new LinqtoSQLiteDataContext();
var book = _connection.books.SingleOrDefault(b_no => b_no.id == book_id);
// Outer table to get rounded corner...
var table = new PdfPTable(1) { WidthPercentage = 48, HorizontalAlignment = alignment };
// Inner table: First cell for QR code and second cell for book's informations.
var inner_table = new PdfPTable(2) { WidthPercentage = 100 };
inner_table.DefaultCell.Border = Rectangle.NO_BORDER;
var inner_measurements = new[] { 40f, 60f };
inner_table.SetWidths(inner_measurements);
// Generate QR code in the `Tools` class, `GenerateQR` method.
System.Drawing.Image image = Tools.GenerateQR(100, 100, book?.isbn);
var pdfImage = iTextSharp.text.Image.GetInstance(image, System.Drawing.Imaging.ImageFormat.Jpeg);
var qr = iTextSharp.text.Image.GetInstance(pdfImage);
var a = new PdfPCell(qr) { Border = Rectangle.NO_BORDER };
var b = new PdfPCell(new Phrase(book?.name, font_normal)) { Border = Rectangle.NO_BORDER };
inner_table.AddCell(a);
inner_table.AddCell(b);
var s = new PdfPCell(inner_table)
{
CellEvent = new RoundRectangle(),
Border = Rectangle.NO_BORDER,
Padding = 2,
HorizontalAlignment = Element.ALIGN_LEFT
};
table.AddCell(s);
doc.Add(table);
i++;
}
}
These codes bring me labels like this:
But I want to get labels like this:
Because if I manage getting labels side by side, I print it to computer labels easily. Here is the computer label that I want to print to on it:
How can I iterate tables side by side?
Use one outer Table with
new PdfPTable(2) { WidthPercentage = 100 }
Then add all your inner tables to this one and at last add the outer table to the document. This way there is NO need to use that toggeling left/right alignment.
:edit:
var table = new PdfPTable(2) { WidthPercentage = 100 };
foreach (var book_id in books_ids)
{
// Book's informations are retrieved from Linq Connect Model.
var _connection = new LinqtoSQLiteDataContext();
var book = _connection.books.SingleOrDefault(b_no => b_no.id == book_id);
// Outer table to get rounded corner...
// Inner table: First cell for QR code and second cell for book's informations.
var inner_table = new PdfPTable(2) { WidthPercentage = 100 };
inner_table.DefaultCell.Border = Rectangle.NO_BORDER;
var inner_measurements = new[] { 40f, 60f };
inner_table.SetWidths(inner_measurements);
// Generate QR code in the `Tools` class, `GenerateQR` method.
System.Drawing.Image image = Tools.GenerateQR(100, 100, book?.isbn);
var pdfImage = iTextSharp.text.Image.GetInstance(image, System.Drawing.Imaging.ImageFormat.Jpeg);
var qr = iTextSharp.text.Image.GetInstance(pdfImage);
var a = new PdfPCell(qr) { Border = Rectangle.NO_BORDER };
var b = new PdfPCell(new Phrase(book?.name, font_normal)) { Border = Rectangle.NO_BORDER };
inner_table.AddCell(a);
inner_table.AddCell(b);
PdfPCell labelCell = new PdfPCell(inner_table)
{
CellEvent = new RoundRectangle(),
Border = Rectangle.NO_BORDER,
Padding = 2,
HorizontalAlignment = Element.ALIGN_LEFT
};
table.AddCell(labelCell);
}
doc.Add(table);
Just add page-level table (2 columns, 6 rows) and place each label into individual cell in this page-level table.