I have a XtraTreeList and I assign a huge datasource (with millions of items) to it
xtraTree.TreeViewData = dataSource;
This operation takes 80 seconds to complete, which is totally fine given the amount of nodes.
I'd just like to display a somewhat reliable progress bar to the user, indicating how many nodes have been processed.
I have tried:
looking in the event list, but I only found PrintExportProgress
googling for the topic, hoping I would find something on the DevExpress support pages
I'm using the WinForms variant, version 15.2 if that matters.
This is not about displaying progress while I build the datasource. There are 2 steps:
build the datasource (read from file) - this also takes 60 seconds, but I do that myself and I have no problem here
assign the datasource to the XtraTreeList - works, but I don't get progress information and it needs to be done on the UI thread, which is blocking
This is also not about cross-thread updating of the progress bar. I know how to do that.
Hey I did the same thing in a project that I built using WinForms ... except I only had 4500 items - these items were files that I had to extract data from. What I did is at each file that I processed (at the bottom of my foreach loop) I called a method to update my progress bar on my form:
Form1.UpdateProgressbar();
Inside my Form1.cs, I did this:
public void UpdateProgressbar()
{
progressBar2.Increment(1);
label7.Text = "Processed: " + Convert.ToString(progressBar2.Value) + " out of " + Globals.totalartistcount + " Artists";
label8.Text = "Processed: " + Globals.songcounter + " Songs. Processing: " + Globals.artist;
label9.Text = "Total Number of Songs to process: " + Globals.totalsongcount;
progressBar2.Update();
Application.DoEvents();
}
If I remember right the
Application.DoEvents();
was critical to actually see the progress bar move and the labels update their text. I initialized my progress bar this way:
/* ------ progress bar ------------------------------------------ */
public void InitializeProgressBar(DirectoryInfo di)
{
int songcount = 0;
int artistcount = 0;
int index = 0;
//Get Total number of folders
foreach (var sf in di.GetDirectories())
{
//find index of artist to process
//this is just an array of artist names and if true or false to process
for (int i = 0; i <= Globals.artists.GetUpperBound(0); i++)
{
if (sf.Name == Globals.artists[i, 0])
{
index = i;
break;
}
}
if (Globals.artists[index, 1] != "false")
{
// Get a total number of files to process (MAX)
foreach (var fi in sf.GetFiles("*.mp3"))
{
songcount++;
}
artistcount++;
}
}
Globals.totalartistcount = artistcount;
Globals.totalsongcount = songcount;
progressBar2.Minimum = 0;
progressBar2.Maximum = artistcount - 1;
progressBar2.Value = 0;
Application.DoEvents();
}
There, I hope that helps.
Related
I'm writting a PowerPoint AddIn (VSTO) which makes the following (very roughly):
1. Loop through all slides
2. Loop through all tags for each slide and write the tag information to a List-Object
3. Do some calucations on the List-Object and update some columns in the list-Object
4. Loop through the List-Object and write the tags back to the sorresponding slides / tags
I recognized that this code runs for every run slower and slowwer - the 10th run is 3-4 times slower than the first one.
I also see the memory usage goes up for every run.
What are my tools to check where the bottle neck is?
How can I find the problem which makes my code slower for every run?
Is there a way to clear the memory etc. the AddOn uses after each run?
I'm sorry to ask such general question, but please let me know if you need more details
My PowerPoint has 32 Slides - for each slide i want to write tags (in this example 49 Tags). Because of updates etc. the code is executed several times by the user. I simulate this by doing it 11 times automatically. I recognize here the same behavior as by user interaction: the writing of the tags for the 32 Slides is getting slower with every execute.
I reduced my code to the minimum which has the same behavior. I tried also to first delete the tags on every slide but without success.
private void btn_DoIt10Times_Click(object sender, EventArgs e)
{
Stopwatch watch = new Stopwatch();
watch.Start();
SlideTags_Write();
watch.Stop();
//MessageBox.Show("Time spend: " + watch.Elapsed);
for (int i = 1; i <= 10; i++)
{
SlideTags_Write();
}
Stopwatch watch2 = new Stopwatch();
watch2.Start();
SlideTags_Write();
watch2.Stop();
MessageBox.Show("Time 1st run: " + watch.Elapsed + "\n Time 11th run: " + watch2.Elapsed);
}
public void SlideTags_Write()
{
PowerPoint.Presentation oPresentation = Globals.ThisAddIn.Application.ActivePresentation;
foreach (PowerPoint.Slide oSlide in oPresentation.Slides)
{
//for (int iTag = 1; iTag <= oSlide.Tags.Count; iTag++)
//{
// oSlide.Tags.Delete(oSlide.Tags.Name(iTag));
//}
for (int iTag = 1; iTag < 50; iTag++)
{
oSlide.Tags.Add("Tag_" + iTag.ToString(), "Tag Value " + iTag.ToString());
}
}
}
I'm doing a project where I'm outputting the frequencies from real time mic input through fft to a txt doc and then retrieving (or trying to retrieve) them to a list of 4 frequencies. My list array is turning out empty, ie the console prints [] and no numbers in them. Pl tell me what is wrong with the logic/code. This is within the void draw()
for (int i = 0; i<fft.specSize(); i++) {
float freq = fft.getFreq(i);
int freqint = (int) freq;
//println(freqint);
output.println(freqint);}
Scanner input = new Scanner("...\\list.txt");
while (input.hasNextInt()) {
list.get(input.nextInt(4));
}
println(list);
input.close();
Split your taks into subtasks:
get FFT data (and 4 frequencies)
Save/Load float values to disk
Put the 1 and 2 together
It looks like you already have the first part done.
It's unclear what the 4 frequencies are, but you can figure that out on your own.
The part that is confusing is that you call the get FFT data once then try to save it straight to disk. I'm not 100% that's what you mean to do.
Double check if you need to save few samples/seconds worth of FFT data first.
I would imagine a more generic scenario like this:
load previously saved FFT data (if any)
process FFT data (for as long as needed - might need a start/stop boolean) and append
save current FFT data
Moving on to saving and loading data.
You've got a few of options build into Processing for storing data:
Strings via saveStrings()/loadStrings()
CSV Table via saveTable()/loadTable()/Table
JSON via JSONObject/JSONArray and available load/save functions
XML
I recommend reading Daniel Shiffman's Data Tutorial
Dealing with saving/loading floating point values to disk alone,
here's a basic proof of concept snippet using Strings:
int fftSpecSize = 10;//this will be fft.specSize() in your case
String values = "";
for(int i = 0 ; i < fftSpecSize; i++){
//random(1) is a placeholder for fft.getFreq(i);
values += random(1);
//if it's not the last value, add a separator character (in this case space)
if(i < fftSpecSize-1){
values += " ";
}
}
println("values to save:");
println(values);
println();
//save data
saveStrings("fftSingleRead.txt",values.split(" "));
//load data
String[] readValues = loadStrings("fftSingleRead.txt");
//print raw loaded data
println("readValues from .txt file:");
println(readValues);
println();
//parse values:
for(int i = 0 ; i < readValues.length; i++){
float value = float(readValues[i]);
println("readValues[",i,"] = ",value);
}
additionally here's a Table example too:
Table fftValues;
int specSize = 10;
//create a new table
fftValues = new Table();
//add columns - one per FFT bin
for(int i = 0 ; i < specSize; i++){
fftValues.addColumn();
}
//add some data, a row per reading
//create a new row
TableRow newRow = fftValues.addRow();
//add each fft value to the row
for(int fftCount = 0 ; fftCount < specSize; fftCount++){
//placeholder for newRow.setFloat(fftCount,fft.getFreq(fftCount));
newRow.setFloat(fftCount,random(1));
}
//add the row to the table
fftValues.addRow(newRow);
//save to disk
saveTable(fftValues,"fftValues.csv","csv");
//load from disk
Table readValues = loadTable("fftValues.csv","csv");
//access the data that has been saved in the table
for(int rowCount = 0; rowCount < readValues.getRowCount(); rowCount++){
TableRow currentRow = readValues.getRow(rowCount);
print("row[",rowCount,"] = ");
for(int columnCount = 0; columnCount < currentRow.getColumnCount(); columnCount++){
float value = currentRow.getFloat(columnCount);
print(value);
if(columnCount < currentRow.getColumnCount() - 1){
print(",");
}
}
println();
}
Try the code, see the output, read the comments, read the reference, tweak/retry/understand and adapt to your problem.
I can sort (descending) my displayed results by a selected value using this code:
PivotField field = pivotTable.RowFields[0];
field.IsAutoSort = true;
field.IsAscendSort = false;
field.AutoSortField = 1;
This is what I see (Total Purchases displayed are indeed shown from most to least):
Or, I can only display Description ranges whose "Percentage of Total" value is at least 1% with this code:
private void HideItemsWithFewerThan1PercentOfSales()
{
int FIRST_TOTAL_PRICE_ROW = 8;
int ROWS_BETWEEN_PERCENTAGES = 4;
var pivot = pivotTableSheet.PivotTables[0];
var dataBodyRange = pivot.DataBodyRange;
int currentRowBeingExamined = FIRST_TOTAL_PRICE_ROW;
int rowsUsed = dataBodyRange.EndRow;
pivot.RefreshData();
pivot.CalculateData();
// Get grand total of purchases for all items and months, and calculate what 1% of that is
Cell totalTotalPurchasesCell = pivotTableSheet.Cells[rowsUsed - 2, _grandTotalsColumnPivotTable + 1];
double totalTotalPurchases = Convert.ToDouble(totalTotalPurchasesCell.Value);
var onePercentOfTotalPurchases = totalTotalPurchases / 100;
// Loop through PivotTable data, hiding where percentage < 0.01 (1%)
while (currentRowBeingExamined < rowsUsed)
{
Cell priceCell = pivotTableSheet.Cells[currentRowBeingExamined, _grandTotalsColumnPivotTable + 1];
String priceStr = priceCell.Value.ToString();
Double price = Convert.ToDouble(priceStr);
if (price < onePercentOfTotalPurchases)
{
pivotTableSheet.Cells.HideRows(currentRowBeingExamined - 1, ROWS_BETWEEN_PERCENTAGES);
}
currentRowBeingExamined = currentRowBeingExamined + ROWS_BETWEEN_PERCENTAGES;
}
}
...like so:
...but I can't get them both to work at the same time. So I can either hide the Descriptions with less than 1% of the percntage OR I can sort by Total Purchases descending, but I'm not able to accomplish both at the same time. My code to try to accomplish both is as follows:
. . .
pivotTable.AddFieldToArea(PivotFieldType.Row, DESCRIPTION_COLUMN);
pivotTable.RowHeaderCaption = "Description";
// Dragging the second field to the column area.
pivotTable.AddFieldToArea(PivotFieldType.Column, MONTHYR_COLUMN);
pivotTable.ColumnHeaderCaption = "Months";
// Dragging the third field to the data area.
pivotTable.AddFieldToArea(PivotFieldType.Data, TOTALQTY_COLUMN);
pivotTable.DataFields[0].DisplayName = "Total Packages";
pivotTable.AddFieldToArea(PivotFieldType.Data, TOTALPRICE_COLUMN);
pivotTable.DataFields[1].DisplayName = "Total Purchases";
. . .
// Sort by "Total Purchases" descending
PivotField field = pivotTable.RowFields[0];
field.IsAutoSort = true;
field.IsAscendSort = false;
field.AutoSortField = 1; // This is the "Total Purchases" field
pivotTable.PivotTableStyleType = PivotTableStyleType.PivotTableStyleLight16;
pivotTable.RefreshDataFlag = true;
pivotTable.RefreshData();
pivotTable.CalculateData();
pivotTable.RefreshDataFlag = false;
List<String> contractItemDescs = GetContractItemDescriptions();
ColorizeContractItemBlocks(contractItemDescs);
HideItemsWithFewerThan1PercentOfSales();
FreezePanePivotTable(HEADER_ROW, 2);
FormatPivotTableNumbers();
ConfigureForPrinting(pivotTableSheet.Cells.Rows.Count);
It's as if the sorting order is not being respected when HideItemsWithFewerThan1PercentOfSales() is called - the row numbers that method "sees" is not the row numbers according to the sorting that has been established.
How can I get both the sorting AND the hiding to work?
NOTE: Calling HideItemsWithFewerThan1PercentOfSales(); prior to the sorting code does NOT work - it still shows/hides some of the wrong things.
Please check the reply in this thread in Aspose.Cells forum.
Note: I am working as Developer Evangelist at Aspose
I'm trying to paginate items using jQuery Isotope 2.1. I have a set of items which can be filtered. I'd like to be able to limit the displayed items using a range. If I want to display 10 items per page, I'd tell it show all items between 11 and 20 in the filtered set for page 2, for example.
To make matters more complex, items can be sorted as well.
Is there any way to do this?
I thought about toggling a "active" class on the filtered items, then using JS and CSS I would only show items with the "active" class that are within the current range. Not sure if that's the most efficient approach.
Thanks,
Howie
I was able to solve the problem by prototyping the _filter method.
Firstly, I call the _sort method before attempting to filter the items since sorting will affect which items are displayed on each page.
Then I added a few parameters to the options object, such as page and items_per_page. Using these two values, I can calculate the first and last item for the intended page. Even though it's not necessary for pagination, I also added a parameter called activeClass which defaults to active and is added to all matching items. In addition I added and odd-item and an even-item class to each item so that in a list view, for example, I can alternate the row colors.
Lastly, I set a property on the this object called all_matches to the entire set of filtered items. This way I can calculate the total number of pages for my pager. Then I return only the filtered items for the current page.
On the layoutComplete event, I use the page and items_per_page values from the options object in order to calculate the first and last item and update my pager.
I happen to be using Bootstrap along with a customized version of the Bootpag pager which accepts itemsPerPage and totalItems.
You can check out the codepen here. Hope it helps.
Isotope.prototype._filter = function (items)
{
//console.log('FILTER ' + arguments.callee.caller.toString());
var filter = this.options.filter;
filter = filter || '*';
var matches = [];
var all_matches = [];
var hiddenMatched = [];
var visibleUnmatched = [];
var start, end;
//console.log('page: ' + this.options.page + ' items per page: ' +
this.options.items_per_page);
start = (this.options.page - 1) * this.options.items_per_page;
end = this.options.page * this.options.items_per_page;
//console.log('start: ' + start + ' end: ' + end + ' page: ' +
this.options.page);
// we want to set the current value of filteredItems to all items
before we sort
// we must sort first becuase we need to make sure we are showing
// the correct results for each page in the correct order
this.filteredItems = items;
this._sort();
if (this.options.activeClass === undefined ||this.options.activeClass === '')
{
this.options.activeClass = 'active';
}
var test = this._getFilterTest(filter);
// test each item
for (var i = 0, len = items.length; i < len; i++)
{
//console.log('item: ' + i, $(items[i].element).find('.grid-item-title .asset-link').text(), items[i]);
var item = items[i];
if (item.isIgnored)
{
continue;
}
// add item to either matched or unmatched group
var isMatched = test(item);
// add to matches if its a match
if (isMatched)
{
all_matches.push(item);
// before we add it to the matched set, let's make sure if falls within range
// it needs to be part of the current page set otherwise we filter it out
if (all_matches.length > start && all_matches.length <= end)
{
matches.push(item);
var odd_even = (matches.length % 2 === 0) ? 'even-item' : 'odd-item';
$(item.element).addClass(this.options.activeClass + ' ' + odd_even);
} else
{
// we need to reset isMatched if we're not using it on the current page
isMatched = false;
$(item.element).removeClass(this.options.activeClass + ' odd-item even-item');
}
}
// add to additional group if item needs to be hidden or revealed
if (isMatched && item.isHidden)
{
// reveal these items
hiddenMatched.push(item);
} else if (!isMatched && !item.isHidden)
{
// hide these items
visibleUnmatched.push(item);
}
}
var _this = this;
function hideReveal()
{
_this.reveal(hiddenMatched);
_this.hide(visibleUnmatched);
}
if (this._isInstant)
{
this._noTransition(hideReveal);
} else {
hideReveal();
}
// set all matches as a property on 'this' since we'll need it later to build the pager
this.all_matches = all_matches;
return matches;
};
H
I am trying to create a function, that when an arrow link (up or down) is clicked on a certain row, the row will move up or down.
Is there a way to dynamically move rows in the data this way?
(I know there is the RowMoveManager but the requirements request arrow links instead of drag-able)
I found a way to do it, although it might not be the most efficient way. I have a column in my data, rank and I added an onClick function on an arrow moveOneUp(index);
function moveOneUp(rowIndex) {
_grid.dataView.getItem(rowIndex).rank = parseInt(_grid.dataView.getItem(rowIndex).rank)-1 ;
_grid.dataView.getItem(rowIndex-1).rank = parseInt(_grid.dataView.getItem(rowIndex-1).rank)+1;
_grid.dataView.fastSort('rank');
}
If anyone needs the rest of the arrow functions:
function moveOneDown(rowIndex) {
_grid.dataView.getItem(rowIndex).rank = parseInt(_grid.dataView.getItem(rowIndex).rank)+1 ;
_grid.dataView.getItem(rowIndex+1).rank = parseInt(_grid.dataView.getItem(rowIndex+1).rank)-1;
_grid.dataView.fastSort('rank');
}
function moveTop(rowIndex) {
_grid.dataView.getItem(rowIndex).rank = 0 ;
_grid.dataView.fastSort('rank');
}
function moveBottom(rowIndex) {
_grid.dataView.getItem(rowIndex).rank = parseInt(_grid.dataView.getLength())+1;
_grid.dataView.fastSort('rank');
}
function moveOneUp(rowIndex) {
dataViewReorder.beginUpdate();
rowIndex = rowIndex - 1;
dataViewReorder.getItem(rowIndex).intOrd0 = parseInt(dataViewReorder.getItem(rowIndex).intOrd0) - 1;
dataViewReorder.getItem(rowIndex - 1).intOrd0= parseInt(dataViewReorder.getItem(rowIndex - 1).intOrd0) + 1;
dataViewReorder.fastSort('intOrd0');
dataViewReorder.setItems(dataReorder);
dataViewReorder.endUpdate();
gridReorder.setData(dataViewReorder);
gridReorder.render();
}
function moveOneDown(rowIndex) {
dataViewReorder.beginUpdate();
rowIndex = rowIndex - 1;
dataViewReorder.getItem(rowIndex).intOrd0= parseInt(dataViewReorder.getItem(rowIndex).intOrd0) + 1;
dataViewReorder.getItem(rowIndex + 1).intOrd0= parseInt(dataViewReorder.getItem(rowIndex + 1).intOrd0) - 1;
dataViewReorder.fastSort('intOrd0');
dataViewReorder.setItems(dataReorder);
dataViewReorder.endUpdate();
gridReorder.setData(dataViewReorder);
gridReorder.render();
}