I have a pivot table, and I am trying to select certain pivot items based on values in an array. I need this process to go faster, so I have tried using application.calculation = xlcalculationmanual and pivottables.manualupdate = true, but neither seem to be working; the pivot table still recalculates each time I change a pivot item.
Is there something I can do differently to prevent Excel from recalculating each time?
Here is my code:
Application.Calculation = xlCalculationManual
'code to fill array with list of companies goes here
dim PT As Excel.PivotTable
Set PT = Sheets("LE Pivot Table").PivotTables("PivotTable1")
Sheets("LE Pivot Table").PivotTables("PivotTable1").ManualUpdate = True
dim pivItem As PivotItem
'compare pivot items to array. If pivot item matches an element of the array, make it visible=true, otherwise, make it visible=false
For Each pivItem In PT.PivotFields("company").PivotItems
pivItem.Visible = False 'initially make item unchecked
For Each company In ArrayOfCompanies()
If pivItem.Value = company Then
pivItem.Visible = True
End If
Next company
Next pivItem
pivottable.ManualUpdate [ = setting ]
True causes RefreshTable to clear data from the pivot table, rather than refreshing it
False allows RefreshTable to work normally.
Default is False.
This property is reset to False automatically after the calling procedure ends (important)
This property should be set to true just before you make an update (e.g. changing pivot item Visible property)
Below is some code written in C# as an example:
private void FilterByPivotItems(PivotField pf, List<string> pivotItemNames)
{
PivotItems pis = pf.ChildItems;
if (pf.Orientation != 0)
{
int oldAutoSortOrder = 0;
if (pf.AutoSortOrder != (int)Constants.xlManual)
{
oldAutoSortOrder = pf.AutoSortOrder;
pf.AutoSort((int)Constants.xlManual, pf.Name);
}
int pivotItemsCount = pf.PivotItems().Count;
for (int i = 1; i <= pivotItemsCount; i++)
{
PivotItem pi = pf.PivotItems(i);
// check if current pivot item needs to be hidden (if it exists in pivotItemNames)
var match = pivotItemNames.FirstOrDefault(stringToCheck => stringToCheck.Equals(pi.Value));
if (match == null)
{
TryFilterPivotItems(pi, false, true);
}
else
{
TryFilterPivotItems(pi, true, true);
}
}
if (oldAutoSortOrder != 0)
{
pf.AutoSort(oldAutoSortOrder, pf.Name);
}
PivotTable pt = pf.Parent as PivotTable;
if (pt != null)
{
// changing a pivot item triggers pivot table update
// so a refresh should be avoided cause it takes a lot and is unnecessary in this case
pt.Update();
}
}
}
private void TryFilterPivotItems(PivotItem currentPI, bool filterValue, bool deferLayoutUpdate = false)
{
try
{
PivotField pf = currentPI.Parent;
PivotTable pt = pf.Parent as PivotTable;
if (currentPI.Visible != filterValue)
{
if (deferLayoutUpdate == true && pt != null)
{
// just keep these three lines stick together, no if, no nothing (otherwise ManualUpdate will reset back to false)
pt.ManualUpdate = true;
currentPI.Visible = filterValue;
// this may be redundant since setting Visible property of pivot item, resets ManualUpdate to false
pt.ManualUpdate = false;
}
else
{
currentPI.Visible = filterValue;
}
}
}
catch (Exception ex)
{
}
}
private void TryFilterPivotItems(PivotField pf, string itemValue, bool filterValue, bool deferLayoutUpdate = false)
{
try
{
PivotItem currentPI = pf.PivotItems(itemValue);
TryFilterPivotItems(currentPI, filterValue, deferLayoutUpdate);
}
catch (Exception ex)
{
}
}
As a conclusion, ManualUpdate property change doesn't stay for long (in my tests, I could see that it gets reset to false as soon as possible, so that's why I recommended you to set it to true whenever you want to make a change for a pivot item)
For more info on what means an update in Excel, you can check the following:
Pivot Refresh vs. Update – is there a real difference?
References:
Title: Programming Excel with VBA and .NET
By: Jeff Webb, Steve Saunders
Print ISBN: 978-0-596-00766-9 | ISBN 10: 0-596-00766-3
Ebook ISBN: 978-0-596-15951-1 | ISBN 10: 0-596-15951-X
Related
I have a following sql code, if I set AutoDetectChangesEnabled and ValidateOnSaveEnabled to false. When there is a race condition in database, is it possible that my string process is processing half way then exit the using.
using (DbContext dbContext = new DbContext()) {
dbContext.Configuration.AutoDetectChangesEnabled = false;
dbContext.Configuration.ValidateOnSaveEnabled = false;
string a = dbContext.sp_getsomething().FirstOrDefault();
string b = a.substring(2);
//and other string processing
}
I want to add a listener to the select button which gets the multiple rows selected in the checklist tableviewer. It then proccedes to check those boxes.
My question is how do I get the list of rows selected in the tableviewer?
Here is the code for the table:
private void createCheckViewer(Composite parent){
tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.MULTI| SWT.BORDER | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL);
if ( (GanttFrame.getListOfFunctionTasks()!= null)){
if (!(GanttFrame.getListOfFunctionTasks().isEmpty())){
// Data Rows
for (int i = 0; i < GanttFrame.getListOfFunctionTasks().size(); i++) {
tableViewer.add(GanttFrame.getListOfFunctionTasks().get(i));
GanttFrame.getListOfFunctionTasks().get(i).setCheckId(i);
}
}
}
// flow trace or function trace
String columnHeader;
if (TraceData.getFlowTraceFlag()){
columnHeader = "Flow Traces";
}else{
columnHeader = "Function Traces";
}
// define layout for the viewer
gridData = new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1);
gridData.heightHint = 400;
tableViewer.getControl().setLayoutData(gridData);
tableViewer.addCheckStateListener(this.getCheckListListener());
final Table table = tableViewer.getTable();
TableLayout layout = new TableLayout();
TableViewerColumn col = new TableViewerColumn(tableViewer, SWT.LEAD);
col.getColumn().setText(columnHeader);
layout.addColumnData(new ColumnWeightData(500));
table.setLayout(layout);
table.setHeaderVisible(true);
table.setLinesVisible(true);
}
Use:
IStructuredSelection selection = (IStructuredSelection)tableViewer.getSelection();
You then have various choices for processing the selection:
Object [] selections = selection.toArray();
List<?> selections = selection.toList();
Iterator<?> iterator = selection.iterator();
The predictive-input of iOS8 calls the following delegate method of UITextView multiple times resulting in the selected word being inserted multiple times into the view.
This code works for typing single letters and copy/paste but not when using the predictive-input bar; why not?
- (BOOL) textView:(UITextView*)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString*)text
{
textView.text = [textView.text stringByReplacingCharactersInRange:range withString:text];
return false;
}
With this code; if I enter an empty UITextView and tap on "The" in the predictive text (autocomplete) view it inserts "The The" into the view by way of making three calls on this method. The parameters passed in for each call are:
range : {0,0} text : #"The"
range : {0,0} text : #"The"
range : {3,0} text : #" "
The space I can understand; but why insert "The" twice?
I got this same issue. It appears that with predictive text, setting textView.text in that delegate method triggers an immediate call to that delegate method again (this only happens with predictive text as far as I know).
I fixed it by just surrounding my textView changes with a guard:
private var hack_shouldIgnorePredictiveInput = false
func textView(textView: UITextView!, shouldChangeTextInRange range: NSRange, replacementText text: String!) -> Bool {
if hack_shouldIgnorePredictiveInput {
hack_shouldIgnorePredictiveInput = false
return false
}
hack_shouldIgnorePredictiveInput = true
textView.text = "" // Modify text however you need. This will cause shouldChangeTextInRange to be called again, but it will be ignored thanks to hack_shouldIgnorePredictiveInput
hack_shouldIgnorePredictiveInput = false
return false
}
I modified the accepted answer from Richard Venable, because, as JLust noted in the comment, that 3rd call with the space was throwing me off.
I added
private var predictiveTextWatcher = 0
And
if predictiveTextWatcher == 1 {
predictiveTextWatcher = 0
return false
}
if hack_shouldIgnorePredictiveInput {
predictiveTextWatcher += 1
hack_shouldIgnorePredictiveInput = false
return false
}
It's all pretty hacky, but better than nothing.
Best,
Not an answer, but a safer workaround:
class TextViewTextChangeChecker {
private var timestamp: TimeInterval = 0
private var lastRange: NSRange = NSRange(location: -1, length: 0)
private var lastText: String = ""
func shouldChange(text:String,in range: NSRange) -> Bool {
let SOME_SHORT_TIME = 0.1
let newStamp = Date().timeIntervalSince1970
let same = lastText == text && range == lastRange && newStamp - timestamp < SOME_SHORT_TIME
timestamp = newStamp
lastRange = range
lastText = text
return !same
}
}
still this didn't helped me because changing the textView from the shouldChangeTextInRange function changed the autocapitalizationType to .word (only by behaviour, not the field itself).
I try to refresh the data of jTable upon deletion of selected row. Here are my codes to set up table :
private JTable getJTableManageReplies() {
jTableManageReplies.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
jTableManageReplies.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
int viewRow = jTableManageReplies.getSelectedRow();
// Get the first column data of the selectedrow
int replyID = Integer.parseInt(jTableManageReplies.getValueAt(
viewRow, 0).toString());
eForumRepliesAdmin reply = new eForumRepliesAdmin(replyID);
replyID = JOptionPane.showConfirmDialog(null, "Are you sure that you want to delete the selected reply? " , "Delete replies", JOptionPane.YES_NO_OPTION);
if(replyID == JOptionPane.YES_OPTION){
reply.deleteReply();
JOptionPane.showMessageDialog(null, "Reply has been deleted successfully.");
SetUpJTableManageReplies();
}
}
}
});
return jTableManageReplies;
}
public void SetUpJTableManageReplies() {
DefaultTableModel tableModel = (DefaultTableModel) jTableManageReplies
.getModel();
String[] data = new String[5];
db.setUp("IT Innovation Project");
String sql = "Select forumReplies.reply_ID,forumReplies.reply_topic,forumTopics.topic_title,forumReplies.reply_content,forumReplies.reply_by from forumReplies,forumTopics WHERE forumReplies.reply_topic = forumTopics.topic_id ";
ResultSet resultSet = null;
resultSet = db.readRequest(sql);
jTableManageReplies.repaint();
tableModel.getDataVector().removeAllElements();
try {
while (resultSet.next()) {
data[0] = resultSet.getString("reply_ID");
data[1] = resultSet.getString("reply_topic");
data[2] = resultSet.getString("topic_title");
data[3] = resultSet.getString("reply_content");
data[4] = resultSet.getString("reply_by");
tableModel.addRow(data);
}
resultSet.close();
} catch (Exception e) {
System.out.println(e);
}
}
And this is my sql statement :
public boolean deleteReply() {
boolean success = false;
DBController db = new DBController();
db.setUp("IT Innovation Project");
String sql = "DELETE FROM forumReplies where reply_ID = " + replyID
+ "";
if (db.updateRequest(sql) == 1)
success = true;
db.terminate();
return success;
}
I called the repaint() to update the table data with the newest data in database and it works. I mean the data after deletion of certain row. However, the existing posts will keep on re-add. Then I add the removeAllElement method to remove all the existing posts because my sql statement is select * from table. Then, there is an error message which is ArrayIndexOutOfBoundsException. Any guides to fix this? Thanks in advance.
I called the repaint() to update the table data with the newest data
in database and it works.
There is no need to call repaint method when data is changed. Data change is handled by the Table Model (DefaultTableModel in this case.) And fireXXXMethods are required to be called whenever data is changed but you are using DefaultTableModel even those are not required. (Since by default it call these methods when ever there is a change.)
I think the problem is in the valuesChanged(..) method. You are getting the value at row 0 but not checking whether table has rows or not. So keep a constraint.
int viewRow = jTableManageReplies.getSelectedRow();
// Get the first column data of the selectedrow
if(jTableManageReplies.getRowCount() > 0)
int replyID = Integer.parseInt(jTableManageReplies.getValueAt(viewRow, 0).toString());
I want to disable one specific row in datagrid in following manner:
1) Highlight one row with a different color
2) Disable checkbox/radio button selection of that row
3) Disable inline editing of cells present in that row but allow inline editing for other rows.
Pls. help if you have any ideas.
You can use a combination of the following functions to extract stuff
// as example, one of youre items uses identifier:'id' and 'id:10'
var identifier = '10';
var item = store._arrayOfTopLevelItems[10]; // you probably have this allready
var index = grid.getItemIndex(item); // find which index it has in grid
var rowNode = grid.getRowNode(index); // find a DOM element at that index
You will have the <div> as rowNode, it contains a table with cells (as many as you got columns). Set its background-color
The checkbox thing, you will prly know which cell-index it has
var cellNode = dojo.query('td[idx='+cellIndex+']', rowNode)[0];
// with cellType Bool, td contains an input
var checkbox = cellNode.firstChild;
Editing is another store really.. works in focus handlers. To override it, you must keep like an array of rows which you dont want editable (allthough the cell.editable == true).
function inarray(arr, testVal) {
return dojo.some(arr, function(val) { return val == testVal }).length > 0
}
grid.setNonEditable = function (rowIndex) {
if(! inarray(this.nonEditable,rowIndex) )
this.nonEditable.push(rowIndex);
}
grid.setEditable = function (rowIndex) {
this.nonEditable = dojo.filter(this.nonEditable, function(val) { return val != rowIndex; });
}
var originalApply = grid.onApplyEdit
grid.onApplyEdit = function(inValue, inRowIndex) {
if(! inarray(this.nonEditable,inRowIndex) )
originalApply.apply(this, arguments);
}
If you are using dojox.grid.DataGrid you can use canEdit function to disable row editing or cell editing :
grid = new dojox.grid.DataGrid({
canEdit: function(inCell, inRowIndex) {
var item = this.getItem(inRowIndex);
var value = this.store.getValue(item, "name");
return value == null; // allow edit if value is null
}
}