My google script is slowing down my spreadsheet very badly - performance

I'm a total beginner when it comes to writing scripts but somehow managed to copy-paste/write this script that protocols the date when a specific cell has been updated. Somehow the script slows down my spreadsheet so badly that I have to wait a few seconds for every change I make. I used the s.getRange() function instead of s.getActiveCell() because in some cases I want to change up to 30 cells at once and it should then protocol all the changes. Could this maybe slowdown my sheet? Or does anyone have other ideas how I can speed up my sheet?
Why I entered the following functions:
(r.getRow() !1 & r.getRow() !=2) so that the 2 title rows can be change without being protocoled
var name1versandstatus = s.getRange("datum1versandspalte") so that I can insert new columns without affecting the scripts function
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "Strukturierung" ) {
var r = s.getActiveRange(); //
if ( r.getRow() !=1 & r.getRow() !=2) {
var name1versandstatus = s.getRange("datum1versandspalte")
if( r.getColumn() == name1versandstatus.getColumn()) {
if(r.getValue() == "Versendet"){
var nextCell = r.offset(0, 1);
nextCell.setValue(new Date());
}
}
}
}
}

Related

Photoshop CC2019 auto-update all linked smart objects including nested ones

I have Photoshop CC2019 PSD document containing several smart objects that contains other smart objects that contains other smart objects. Some of these have linked layers. Normally, such images are not updated automatically (which is extremely annoying, Adobe!) but you have to manually update each of them once the linked image content has changed.
There is a .jsx script file named "Update All Modified Content.jsx" which auto-updates linked layers (PNG image in my case) but only if the smart object is in the top most document - that is no nested smart objects with linked layers are updated automatically.
My question is: does anyone know how to update the content of the above mentioned .jsx file so that it would auto-update all linked images across all the smart objects in PSD document including nested ones?
For those who care or would be willing to help updating the code here it is:
// Update all modified content
var idplacedLayerUpdateAllModified = stringIDToTypeID( "placedLayerUpdateAllModified" );
executeAction( idplacedLayerUpdateAllModified, undefined, DialogModes.NO );
So, after spending half a day with it I finally solved it myself. Here is the code:
#target photoshop
// SET INITIAL ACTIVE DOCUMENT
var mainDocument = app.activeDocument;
// SAVE THE DOCUMENT NAME FOR FUTURE USE
var mainDocName = mainDocument.name;
// RUN THE MAIN UPDATE FUNCTION
mainDocument.suspendHistory("processAllSmartObjects", "autoupdateAllSmartObjects(mainDocument, 0)");
// FINALLY SAVE THE MAIN DOCUMENT
mainDocument.save();
function autoupdateAllSmartObjects(theParent, prevVal) {
// FUNCTION TO TEST IF SMARTOBJECT IS LINKED
function isLinkedSO(obj) {
var localFilePath = "";
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID('Lyr '), obj.id);
var desc = executeActionGet(ref);
var smObj = desc.getObjectValue(stringIDToTypeID('smartObject'));
var isLinked = false;
// TEST IF IT HAS LINKED FILE
try {
var localFilePath = smObj.getPath(stringIDToTypeID('link'));
isLinked = true;
} catch(e) {
//
}
return isLinked;
}
// FUNCTION TO UPDATE LINKED SMART OBJECT
function doTheUpdate(LYR, stackNr) {
// SET ACTIVE LAYER TO ACTUALY ITERATED ONE
app.activeDocument.activeLayer = LYR;
// RUN IN "SILENT" MODE
app.displayDialogs = DialogModes.NO;
var layer = app.activeDocument.activeLayer;
// IF ACTIVE LAYER IS SMARTOBJECT
if (layer.kind == "LayerKind.SMARTOBJECT") {
//alert(layer);
// OPEN THE SMARTOBJECT
app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
// DO THE ACTUAL FILE UPDATE
var idplacedLayerUpdateAllModified = stringIDToTypeID( "placedLayerUpdateAllModified" );
executeAction( idplacedLayerUpdateAllModified, undefined, DialogModes.NO);
// IF IT IS NOT THE "CORE/MAIN" DOCUMENT
if(stackNr > 0) {
// SAVE CHANGES (UPDATE) AND CLOSE IT
app.activeDocument.close(SaveOptions.SAVECHANGES);
}
// CONTINUE INSIDE THIS ACTIVE SMARTOBJECT
autoupdateAllSmartObjects(app.activeDocument, stackNr);
}
return;
}
// FUNCTION TO PARSE GROUPS
function parseGroup(LYR) {
var groupLayers = LYR.layers;
// IF GROUP IS NOT EMPTY
if(groupLayers.length > 0) {
// PARSE ALL LAYERS IN THE GROUP
for (var i = groupLayers.length - 1; i >= 0; i--) {
var lyr = groupLayers[i];
// IF NOT LOCKED = NOT EDITABL:E
if(!lyr.allLocked) {
// YET ANOTHER GROUP?
if (lyr.typename == "LayerSet") {
// IF IT IS NOT EMPTY
if (lyr.layers.length > 0) {
// RE-RUN THE SCRIPT ANEW WITH THE SELECTED GROUP AS LAYERS SOURCE
autoupdateAllSmartObjects(lyr, 0);
}
// LAYERS
} else if (lyr.typename == "ArtLayer") {
// IF THE LAYER IS SMARTOBJECT
if (lyr.kind == LayerKind.SMARTOBJECT) {
// IF THE LAYER IS SET TO "visible" (THAT IS: NOT DISABLED)
if(lyr.visible){
// TEST IF THE SMARTOBJECT IS ACTUALLY LINKED
if(!isLinkedSO(lyr)) {
// RUN THE UPDATE SUB-FUNCTION
doTheUpdate(lyr, i);
}
}
}
}
}
}
}
}
// PARSE ALL THE LAYERS
for (var i = theParent.layers.length - 1 - prevVal; i >= 0; i--) {
var theLayer = theParent.layers[i];
// ONLY ArtLayers
if (theLayer.typename == "ArtLayer") {
// IF THE LAYER IS SMARTOBJECT
if (theLayer.kind == LayerKind.SMARTOBJECT) {
// IF THE LAYER IS SET TO "visible" (THAT IS: NOT DISABLED)
if(theLayer.visible){
// TEST IF THE SMARTOBJECT IS ACTUALLY LINKED
if(!isLinkedSO(theLayer)){
// RUN THE UPDATE SUB-FUNCTION
doTheUpdate(theLayer, i);
// IF WE ARE AT THE LAST LAYER IN THE STACK AND IT IS NOT OUR MAIN DOCUMENT
if(i == 0 && app.activeDocument.name !== mainDocName) {
// SAVE CHANGES (UPDATE) AND CLOSE IT
app.activeDocument.close(SaveOptions.SAVECHANGES);
}
}
}
}
// ONLY Groups
} else if (theLayer.typename == "LayerSet") {
// RUN SUB-FUNCTION FOR GROUP PARSING
parseGroup(theLayer);
// ANYTHING ELSE
} else {
autoupdateAllSmartObjects(theLayer, m);
}
}
return;
};
OP's script works!! It was going in loops for me too but after some trial and error, I realised that my smart objects (SO) that are linked across artboards ( - e.g. if you change one SO, it changes on various artboards) - were the issue. I hid all such SO and it works.
so basically, it only works for Smart Objects + copies made via 'New smart object via copy' NOT 'duplicate layer' / copypaste smart objects. If your work contains a 'duplicate layer' SO - it will break the script. You need to hide these objects ( or not work like that all together) before running the script

A simple sort script on Google Sheets is not working

I have a "leaderboard"/"scoreboard", across four sheets, that I need to have auto sorting whenever updated by first Total Score (column 2) and then Total Kills (column 3). These columns are the same across all four sheets.
I've used a very simple script in the past when the scoreboard was limited to one sheet, but I have since expanded it to have Top Ten, Top Four, and Top Two on separate sheets within the same document.
The problem I'm running into: When the script updates one sheet, the other ones seem to flat out stop working entirely; in other words, the script breaks.
Can I please get some advice? I've tried several scripts already from this site, and the basic one I see some success with (but then the script seemingly breaks?) is below.
function sortOnEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("MAIN EVENT");
sheet.sort(3, false).sort(2, false);
}
function sortOnEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TOP TEN");
sheet.sort(3, false).sort(2, false);
}
function sortOnEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TOP FOUR");
sheet.sort(3, false).sort(2, false);
}
function sortOnEdit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TOP TWO");
sheet.sort(3, false).sort(2, false);
}
Ideally, when functioning, the sheets will literally just sort themselves by the Total Score column, with Total Kills being the "tiebreaker" for sorting.
I've included a copy of my sheet if anybody could help:
https://docs.google.com/spreadsheets/d/1a6XGv09TPt5Vnxqfcd1Xba3TGMis5OelGxlvzNDl5CY/edit?usp=sharing
try something like this instead of your scripts:
function onEdit(event){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = event.source.getActiveSheet().getName()
var editedCell = event.range.getSheet().getActiveCell();
if(sheet=="Sheet1"){
var columnToSortBy = 2;
var tableRange = "A3:C10"; //range to be sorted
if(editedCell.getColumn() == columnToSortBy){
var range = ss.getActiveSheet().getRange(tableRange);
range.sort( { column : columnToSortBy, ascending: true } );
}}
else if(sheet=="Sheet2"){
var columnToSortBy = 7;
var tableRange = "A3:C10"; //range to be sorted
if(editedCell.getColumn() == columnToSortBy){
var range = ss.getActiveSheet().getRange(tableRange);
range.sort( { column : columnToSortBy, ascending: true } );
}
else{return}
}}
try this:
function sortOnEdit(e) {
var sh=e.range.getSheet();
var name=sh.getName();
var incl=['MAIN EVENT','TOP TEN','TOP FOUR','TOP TWO'];
if(incl.indexOf(name)==-1) return;
sh.sort(3,false).sort(2,false);
}

Autosort not working anymore: Google spreadsheet

I have a working script on an old version of a Google spreadsheet that isn't working any more.
It was a sorting script which sorts out the rows each time one or more column is modified.
On the new spreadsheet that isn't working any more. I'm trying to figure out why but I can't catch where the error is.
Can anyone help?
function onEdit(e) {
Logger.clear()
Logger.log('Script Start')
var ss = SpreadsheetApp.getActiveSpreadsheet();
Logger.log('ss=%s', ss)
var sheet = ss.getSheets()[0];
Logger.log('sheet=%s',sheet)
Logger.log('SheetName=%s',sheet.getName())
if(sheet.getName()=='MembriForum'){
var editedCell = sheet.getActiveCell();
Logger.log('editedCell=%s', editedCell)
}
var columnToSortBy_1 = 4;
var columnToSortBy_2 = 6;
var range = sheet.getDataRange();
Logger.log('range=%s', range)
if(editedCell.getColumn() == columnToSortBy_1 || editedCell.getColumn() == columnToSortBy_2){
var range = sheet.getRange(range.getRow()+1, range.getColumn(),range.getNumRows()-1,range.getNumColumns() );
Logger.log('range=%s', range)
range.sort([{ column: columnToSortBy_1, ascending: true }, { column: columnToSortBy_2, ascending: true}]);
}
}
I think this is unfortunately due to an issue in new spreadsheets...
See here for details and star it to (hopefully) get more attention from Google.
Your condition will never be true since editedCell.getColumn() will always be 1.

facing performance issues with knockout mapping plugin

I have decent large data set of around 1100 records. This data set is mapped to an observable array which is then bound to a view. Since these records are updated frequently, the observable array is updated every time using the ko.mapping.fromJS helper.
This particular command takes around 40s to process all the rows. The user interface just locks for that period of time.
Here is the code -
var transactionList = ko.mapping.fromJS([]);
//Getting the latest transactions which are around 1100 in number;
var data = storage.transactions();
//Mapping the data to the observable array, which takes around 40s
ko.mapping.fromJS(data,transactionList)
Is there a workaround for this? Or should I just opt of web workers to improve performances?
Knockout.viewmodel is a replacement for knockout.mapping that is significantly faster at creating viewmodels for large object arrays like this. You should notice a significant performance increase.
http://coderenaissance.github.com/knockout.viewmodel/
I have also thought of a workaround as follows, this uses less amount of code-
var transactionList = ko.mapping.fromJS([]);
//Getting the latest transactions which are around 1100 in number;
var data = storage.transactions();
//Mapping the data to the observable array, which takes around 40s
// Instead of - ko.mapping.fromJS(data,transactionList)
var i = 0;
//clear the list completely first
transactionList.destroyAll();
//Set an interval of 0 and keep pushing the content to the list one by one.
var interval = setInterval(function () {if (i == data.length - 1 ) {
clearInterval(interval);}
transactionList.push(ko.mapping.fromJS(data[i++]));
}, 0);
I had the same problem with mapping plugin. Knockout team says that mapping plugin is not intended to work with large arrays. If you have to load such big data to the page then likely you have improper design of the system.
The best way to fix this is to use server pagination instead of loading all the data on page load. If you don't want to change design of your application there are some workarounds which maybe help you:
Map your array manually:
var data = storage.transactions();
var mappedData = ko.utils.arrayMap(data , function(item){
return ko.mapping.fromJS(item);
});
var transactionList = ko.observableArray(mappedData);
Map array asynchronously. I have written a function that processes array by portions in another thread and reports progress to the user:
function processArrayAsync(array, itemFunc, afterStepFunc, finishFunc) {
var itemsPerStep = 20;
var processor = new function () {
var self = this;
self.array = array;
self.processedCount = 0;
self.itemFunc = itemFunc;
self.afterStepFunc = afterStepFunc;
self.finishFunc = finishFunc;
self.step = function () {
var tillCount = Math.min(self.processedCount + itemsPerStep, self.array.length);
for (; self.processedCount < tillCount; self.processedCount++) {
self.itemFunc(self.array[self.processedCount], self.processedCount);
}
self.afterStepFunc(self.processedCount);
if (self.processedCount < self.array.length - 1)
setTimeout(self.step, 1);
else
self.finishFunc();
};
};
processor.step();
};
Your code:
var data = storage.transactions();
var transactionList = ko.observableArray([]);
processArrayAsync(data,
function (item) { // Step function
var transaction = ko.mapping.fromJS(item);
transactionList().push(transaction);
},
function (processedCount) {
var percent = Math.ceil(processedCount * 100 / data.length);
// Show progress to the user.
ShowMessage(percent);
},
function () { // Final function
// This function will fire when all data are mapped. Do some work (i.e. Apply bindings).
});
Also you can try alternative mapping library: knockout.wrap. It should be faster than mapping plugin.
I have chosen the second option.
Mapping is not magic. In most of the cases this simple recursive function can be sufficient:
function MyMapJS(a_what, a_path)
{
a_path = a_path || [];
if (a_what != null && a_what.constructor == Object)
{
var result = {};
for (var key in a_what)
result[key] = MyMapJS(a_what[key], a_path.concat(key));
return result;
}
if (a_what != null && a_what.constructor == Array)
{
var result = ko.observableArray();
for (var index in a_what)
result.push(MyMapJS(a_what[index], a_path.concat(index)));
return result;
}
// Write your condition here:
switch (a_path[a_path.length-1])
{
case 'mapThisProperty':
case 'andAlsoThisOne':
result = ko.observable(a_what);
break;
default:
result = a_what;
break;
}
return result;
}
The code above makes observables from the mapThisProperty and andAlsoThisOne properties at any level of the object hierarchy; other properties are left constant. You can express more complex conditions using a_path.length for the level (depth) the value is at, or using more elements of a_path. For example:
if (a_path.length >= 2
&& a_path[a_path.length-1] == 'mapThisProperty'
&& a_path[a_path.length-2] == 'insideThisProperty')
result = ko.observable(a_what);
You can use typeOf a_what in the condition, e.g. to make all strings observable.
You can ignore some properties, and insert new ones at certain levels.
Or, you can even omit a_path. Etc.
The advantages are:
Customizable (more easily than knockout.mapping).
Short enough to copy-paste it and write individual mappings for different objects if needed.
Smaller code, knockout.mapping-latest.js is not included into your page.
Should be faster as it does only what is absolutely necessary.

Flash AS2 show text one by one from array

I want to dynamically display some text from an array one after another in a dynamic textfield.
var wordList:Array = new Array('one','two','three');
for (var i = 0; i < wordList.length; i++) {
this.text_mc.txt.text = wordlist[i];
// Pause for 3 seconds and then move next
}
its the "Pause for 3 seconds and then move next" part I cant figure out.
Thanks.
track what index of the array you are currently showing, and use the setInterval function to call your 'showNext' function every 3000 milliseconds
ie)
var wordList:Array = new Array('one','two','three');
var curIndex = 0;
renderText(curIndex);
setInterval( showNextText, 3000 );
function showNextText()
{
curIndex++;
renderText(curIndex);
}
function renderText( index:Number )
{
this.text_mc.txt.text = wordlist[index];
}

Resources