Right aligning aggregate columns in Blazorise/DataGrid - alignment

For context, I'm using ABP.IO/Blazorise to show a bunch of transactions.
Aggregate data is returned by from a serverside call. All works well, except for the alignment of those columns. They are 'something' aligned it seems... I would like the correctly right aligned with the other values in the grid rows.
Here's a pic of what it looks like:
And here is the code:
<DataGrid
Striped="true"
TItem="ViewTransactionDetailedDto"
Data="TransactionsList"
AggregateData="AggregatesList"
ReadData="OnDataGridReadAsync"
TotalItems="#TotalCount"
CurrentPage="#CurrentPage"
PageSizeChanged="#OnPageSizeChanged"
ShowPager="true"
ShowPageSizes="true"
Sortable="true"
PageSize="#PageSize">
<DataGridAggregates>
#foreach (var aggregate in ThisReportGridColumns.AggregateColumns)
{
<DataGridAggregate Field="#(aggregate.field)" Aggregate="DataGridAggregateType.Sum" DisplayFormat="{0:N0}"></DataGridAggregate>
}
</DataGridAggregates>
<DataGridColumns>
#{ int index = 0; }
#foreach (var col in ThisReportGridColumns.Columns)
{
var colRefTemplate = col.custom;
if (!col.HasCustomLookup)
{
<DataGridColumn TItem="ViewTransactionDetailedDto"
DisplayOrder="#index"
Field="#(col.field)"
Sortable="#col.sortable"
SortField="#col.sortField"
Caption="#col.caption"
HeaderTextAlignment="#col.BlazorHeaderAlignment()"
TextAlignment="#col.BlazorTextAlignment()">
</DataGridColumn>
}
#if (col.HasCustomLookup)
{
<DataGridColumn TItem="ViewTransactionDetailedDto"
DisplayOrder="#index"
Field="#col.field"
Sortable="#col.sortable"
SortField="#col.sortField"
Caption="#col.caption"
HeaderTextAlignment="#col.BlazorHeaderAlignment()"
TextAlignment="#col.BlazorTextAlignment()">
<DisplayTemplate>
#context.ValueForRefWithName(colRefTemplate)
</DisplayTemplate>
</DataGridColumn>
}
index++;
}
</DataGridColumns>
</DataGrid>
The columns are dynamic, since there are a couple of report layouts.
But the values returned (for column alignment) are the same as in Blazorise.
There doesn't seem to be a way to specify horizontal alignment in a DataGridAggregate.
Ideas?

Related

Vaadin Chart: Second and Subsequent Item Does Not Show on Each X-Tick in Column Stack Chart

Base on the resultset below, I have created a column stack chart. They have been converted to an 4-attribrute object list (called as SKUQtyMetric - all are strings except for Quantity as Integer)
When converting this to a stack chart, I could not get the second item to appear next to the first item in each of the x-ticks (X represents hour). If I am not mistaken, there should only be four DataSeries objects, each representing an outlet and then do an inner loop. Just as a side note, each outlet is designated a color even if there's more than one item (I am keeping a limit of three items to be selected for searching in database), hence there's the outletFromH code below.
The current rendering of the code (using Vaadin Charts 4) is as below:
Map<String, Set<String>> myMaps = new HashMap<String, Set<String>>();
for (SkuQtyMetric item : objList) {
if (!myMaps.containsKey(item.getOutletName())) {
myMaps.put(item.getOutletName(), new HashSet<String>());
}
myMaps.get(item.getOutletName()).add(item.getItemName());
}
String asgnColor = "#ffcccc";
for(Map.Entry<String, Set<String>> map: myMaps.entrySet()) {
DataSeries dataSeries = new DataSeries(map.getKey()+"");
PlotOptionsColumn plotOptions = new PlotOptionsColumn();
plotOptions.setStacking(Stacking.NORMAL);
DataLabels labels = new DataLabels(true);
Style style = new Style();
style.setFontSize("9px");
style.setTextShadow("0 0 3px black");
labels.setStyle(style);
labels.setColor(new SolidColor("white"));
plotOptions.setDataLabels(labels);
ls.add(dataSeries);
for(String itemName: map.getValue()) {
System.out.println("Inside " + map.getKey() + ", value is: " + itemName);
dataSeries.setId(itemName);
for(SkuQtyMetric metric : objList) {
for (Map.Entry<String, String> outletfromH : Constant.SYCARDA_COLOR.entrySet()) {
if (outletfromH.getKey().equalsIgnoreCase(map.getKey())) {
asgnColor = outletfromH.getValue();
}
}
System.out.println("DataSeries Id: " + dataSeries.getId() + " , Item metric name is: "+metric.getItemName());
if(dataSeries.getName().equalsIgnoreCase(metric.getOutletName())) {
if(dataSeries.getId().equalsIgnoreCase(metric.getItemName())) {
DataSeriesItem dataSeriesItem = new DataSeriesItem(xFor(metric.getHourNumber()), metric.getQuantityAmt());
dataSeriesItem.setId(metric.getItemName()+"_setSeriesId");
dataSeriesItem.setColor(new SolidColor(asgnColor));
dataSeries.setStack(metric.getItemName());
plotOptions.setColor(new SolidColor(asgnColor));
dataSeries.setPlotOptions(plotOptions);
dataSeries.add(dataSeriesItem);
}
}
}
}
}
for (int j = 0; j < ls.size(); j++) {
listSeries.add(ls.get(j));
}
chart.getConfiguration().getSubTitle().setText(subpageName);
chart.getConfiguration().setSeries(listSeries);
When rendered, I could only get this result:
That's the current chart but second item (coconut water) is missing, shown with red scribbling. What I am not sure is whether my Map class OR my list objects controlled isn't correct OR it might be that there should be eight not four DataSeries (each being a outlet and a product). If not, is there a much more efficient way to handle the code to render the chart than what I am doing right now?
It should be possible to have multiple DataSeriesItem in the same series that go in the same stack. Four series should be enough, no need to have 8.
You can do it by setting the name of the DataSeriesItem and set the XAxis type to category so that the categories are computed from the point names.
Or by setting numeric X values to the DataSeriesItem and setting the categories to the XAxis as a String[].
Having separate series makes some things easier, like tooltips, and showing/hiding data from the legend. But in theory everything can be in a single series.
In some cases you might need to be sure that data is sorted by X value, or by name if you use the name as categories otherwise some points might not show correctly, you can check if that's your case by checking the browser console for error or warnings about that.

ExcelDataReader 2.1.0 : Read Special Character like '%'

I am using nuget Package named ExcelDataReader in MVC application to read Excel sheet and convert it to HTML.All sounds goof but i am not able to read special character from excel sheet.For example is cell value is "59%" but its reading 0.59.So how can i get exact same string value from excel.I am using following code in Controller to read and display excel to html.
public ActionResult ViewExcelFileData(long? id, int sheetindex)
{
var excelfile = db.ExcelUpload.FirstOrDefault(x => x.FileID == id);
string filePath= string.Format(Server.MapPath("~/App_Data/ExcelUploads/Labor_Excel/") + excelfile.FileName);
System.IO.File.GetAccessControl(filePath);
FileStream stream = System.IO.File.Open(filePath, FileMode.Open, FileAccess.Read);
IExcelDataReader reader = null;
if (excelfile.FileName.EndsWith(".xls"))
{
reader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else if (excelfile.FileName.EndsWith(".xlsx"))
{
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
}
reader.IsFirstRowAsColumnNames = true;
DataSet result = reader.AsDataSet();
reader.Close();
return View(result.Tables[sheetindex]);
}
By returning datatable in View side I am using Following Code in Cshtml.
<table class="gridtable" id="table-1">
<thead class="fixed_headers">
<tr>
#foreach (DataColumn col in Model.Columns)
{
<th>#col.ColumnName</th>
}
</tr>
</thead>
<tbody>
#foreach (DataRow row in Model.Rows)
{
<tr>
#foreach (DataColumn col in Model.Columns)
{
<td>#row[col.ColumnName]</td>
}
</tr>
}
</tbody>
</table>
So is it possible in controller side or View side I can get 59% instead of 0.59?
Here is Two images in which one is belongs to excel and second is HTML.
IMAGE :1
IMAGE 2 :
ExcelDataReader currently does not expose any formatting information, it provides you with the raw values except for dates that are converted to DateTime.
There's an open issue about extending it to provide formatting information, https://github.com/ExcelDataReader/ExcelDataReader/issues/215.
Instead of using the AsDataSet() method, you could read the row one by one and read the value as string. Drawback for this is you need to specify the columns one by one which is a maintainability issue.
while (reader.Read())
{
var value = reader.GetString(0); //Get value of first column
}
I suspect that the AsDataSet() converts the data to its respective data type that's why you are seeing the converted decimal value instead of the actual value in the excel.

Mvc #Html.DisplayFor to return multiplication

#Html.DisplayFor(modelItem => item.Quantity)*(modelItem => item.PartsPrice)
I can display 1 or both item but unable to multiply any easy solution for above situation?
Create Price property in your modal as shown below than after use of Price property to display multiplication in your view page.
Price property declaration in modal.
public decimal Price
{
get
{
return Quantity * PartsPrice;
}
}
Display in razor view page as follow.
#Html.DisplayFor(modelItem => item.Price)
Hope it will be helpful.
You can not calculate like that. You can calculate in model, otherwise if you want to calculate the values in view, you can try the following
#{
var result = Model.Quantity * Model.PartsPrice; // Calculate the price
<span>#result</span>
}
#result will display the calculated value
if suppose the model is collection then, use foreach loop
#{
foreach (var item in Model)
{
var result = item.Quantity * item.PartsPrice; // Calculate the price
<span>#result</span>
}
}

Selenium Webdriver - Fetching Table Data

I want to fetch data from tables in UI. I know about looping through rows and columns using "tr" and "td". But the one the table I have is something like this:
<table>
<tbody>
<tr><td>data</td><th>data</th><td>data</td><td>data</td></tr>
<tr><td>data</td><th>data</th><td>data</td><td>data</td></tr>
<tr><td>data</td><th>data</th><td>data</td><td>data</td></tr>
</tbody>
</table>
How can I make my code generic, so that the occurrence of "TH" in middle can be handled.
Currently, I am using this code :
// Grab the table
WebElement table = driver.findElement(By.id(searchResultsGrid));
// Now get all the TR elements from the table
List<WebElement> allRows = table.findElements(By.tagName("tr"));
// And iterate over them, getting the cells
for (WebElement row : allRows) {
List<WebElement> cells = row.findElements(By.tagName("td"));
for (WebElement cell : cells) {
// And so on
}
}
You could look for all children of tr element without differentiating between td and th. So instead of
List<WebElement> cells = row.findElements(By.tagName("td"));
I would use
List<WebElement> cells = row.findElements(By.xpath("./*"));
Mayby it's too late for the owner of this question, but helpful for other.
List<WebElement> cells = row.findElements(By.xpath(".//*[local-name(.)='th' or local-name(.)='td']"));
// Grab the table
WebElement table = driver.findElement(By.id("searchResultsGrid"));
// Now get all the TR elements from the table
List<WebElement> allRows = table.findElements(By.tagName("tr"));
// And iterate over them, getting the cells
for (WebElement row : allRows) {
List<WebElement> cells = row.findElements(By.tagName("td"));
for (WebElement cell : cells) {
System.out.println("content >> " + cell.getText());
}
}
using cell.getText() would simply work
You don't need to loop through elements. Instead, use a ByChained locator.
If you table looks like this:
<table>
<tbody>
<tr><th>Col1</th><th>Col2</th><th>Col3</th></tr>
<tr><td>data</td><td>data</td><td>data</td></tr>
<tr><td>data</td><td>data</td><td>data</td></tr>
<tr><td>data</td><td>data</td><td>data</td></tr>
</tbody>
</table>
The locate like this:
By tableBodyLocator = By.xpath(".//table/tbody");
By headerRowLocator = By.xpath(".//tr[position()=1]");
By dataRowsLocator = By.xpath(".//tr[not(position()=1)]");
By headerRowLocator = new ByChained(tableBodyLocator, headerRowLocator);
List<WebElement> weHeaders = driver.findElement(headerRowLocator)
.findElements(By.xpath(".//th");
List<WebElement> allRowData = driver.findElements(tableBodyLocator, dataRowsLocator);
WebElement row1Data = allRowData.get(0);
WebElement row2Data = allRowData.get(1);
etc.
yes it is working for c# with selenium...
IList<IWebElement> cells = row.findElements(By.xpath(".//*[local-name(.)='th' or local-name(.)='td']"));
IWebElement table = driver.FindElement(By.Id("id"));
List<IWebElement> allRows = new List<IWebElement> (table.FindElements(By.TagName("tr")));
foreach (var Row in allRows)
{
List<IWebElement> cells = new List<IWebElement>( Row.FindElements(By.TagName("td")));
foreach (var cel in cells)
{
string test = cel.Text;
}
}
The below code you can not only get the rows and columns of the table but also you can get the order in which they are in the Browser,this is mainly handy if you have a nested structures in the TD column as in your case.
public DataTable StoreHtmlTableToDataTable(IWebElement tblObj,bool isFirstRowHeader = true)
{
DataTable dataTbl = new DataTable();
int rowIndex = 0;
try
{
//_tblDataCollection = new List<TableDataCollection>();
var tblRows = ((IJavaScriptExecutor)DriverContext.Driver).ExecuteScript("return arguments[0].rows; ", tblObj);
if (tblRows != null)
{
//Iterate through each row of the table
foreach (IWebElement tr in (IEnumerable)tblRows)
{
int colIndx = 0;
DataRow dtRow = dataTbl.NewRow();
// Iterate through each cell of the table row
var tblCols = ((IJavaScriptExecutor)DriverContext.Driver).ExecuteScript("return arguments[0].cells; ", tr);
foreach (IWebElement td in (IEnumerable)tblCols)
{
//add the header row of the table as the datatable column hader row
if (rowIndex == 0)
{
dataTbl.Columns.Add("Col" + colIndx.ToString(), typeof(string));
}
dtRow["Col"+colIndx.ToString()] = td.Text;
//loop through any child or nested table structures if you want using the same approach for example links,radio buttons etc inside the cell
//Write Table to List : This part is not done yet
colIndx++;
}
dataTbl.Rows.Add(dtRow);
rowIndex++;
}
}
}
catch (Exception)
{
throw;
}
//if first row is the header row then assign it as a header of the datatable
if (isFirstRowHeader)
{
dataTbl = this.AssignDataTableHeader(dataTbl);
}
return dataTbl;
}
TableDriver (https://github.com/jkindwall/TableDriver.Java) supports cells with both td and th tags. Using TableDriver with your example table would look something like this:
Table table = Table.createWithNoHeaders(driver.findElement(By.id(searchResultsGrid), 0);
List<TableRow> allRows = table.getRows();
for (TableRow row : allRows) {
List<TableCell> cells = row.getCells();
for (TableCell cell : cells) {
// Access the cell's WebElement like this: cell.getElement()
}
}

Advanced ASP.NET WebGrid - Dynamic Columns and Rows

I'm trying to create a WebGrid which has to be very dynamic. The columns are defined in a list, which I've done like so:
#{
List<WebGridColumn> columns = new List<WebGridColumn>();
foreach (var column in Model.Columns)
{
columns.Add(new WebGridColumn() { ColumnName = column.Name, Header = column.Name });
}
}
#grid.GetHtml(
columns: columns)
All well and good, but the problem I have is with the rows. I'll try and explain...
For this question let's say we have two columns for Name and Address.
I have a collection of row objects, lets say SearchResult objects. A SearchResult contains a Dictionary of any number of attributes, such as Name, Address, Phone, Height, Bra Size, or anything (think of the EAV pattern). I need to access the attributes based on Column Name.
I figured I could do this using format, but I can't seem to figure it out. I want something like this:
columns.Add(new WebGridColumn() { ColumnName = column.Name, Header =
column.Header, Format = #<text>#item.Attributes[column.Name]</text> });
This sort of works but despite creating the format for the separate columns, the rows get populated with only the last column's format. i.e.:
Name Address
1 Main Street 1 Main Street
45 Paradise Av 45 Paradise Av
etc
I think it should work if you leave out the "ColumnName" (superfluous anyway), and also make the dynamic expression a bit more explicit:
columns.Add(
new WebGridColumn() {
Header = column.Header,
Format = (item) => #Html.Raw("<text>" + #item.Attributes[column.Name] + "</text>")
}
);
This issue is related to reference variables. You need to have the Format property in terms of the other properties of the WebGridColumn. This is how I would do it:
#{
List<WebGridColumn> columns = new List<WebGridColumn>();
foreach (var column in Model.Columns)
{
var col = new WebGridColumn();
col.Header = column.Name;
col.Format = (item) => #Html.Raw("<text>" + #item.Attributes[col.Header] + "</text>");
columns.Add(col);
}
}

Resources