Photoshop Script Select all visible Artboards - javascript

I've been trying to find a way to select all visible artboards, so i can later Quick Export them all as PNGs. I'd also love if i've could also include the exporting part inside the script, but that's not the main problem now.
I have this code that finds all the visibile artboards and stores them inside visibleArtboards, but I can't seem to find a way to make a selection of them.
var artboards = activeDoc.layers;
var visibleArtboards = [];
for (var i=0; i<artboards.length; i++){
if(artboards[i].visible){
visibleArtboards.push(artboards[i]);
}
}
activedoc.activeLayer can make a selection, but only of 1 single artboard.
If anybody can help me with the missing piece, I'd appreciate it a lot

You can get the layer ID of the artboards and add that to a selection. Using your code, visibleArtboards now is the ID of the artboard layers.
// call the source document
var activeDoc = app.activeDocument;
var artboards = activeDoc.layers;
var visibleArtboards = [];
for (var i=0; i<artboards.length; i++)
{
if(artboards[i].visible)
{
// select ID as we go along
var layerID = artboards[i].id;
visibleArtboards.push(layerID);
}
}
// Loop over the layers again and select all the art boards
for (var i=0; i<visibleArtboards.length; i++)
{
// add to current selection of layers
select_by_ID(visibleArtboards[i], true);
}
function select_by_ID(id, add)
{
if (add == undefined) add = false;
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putIdentifier(charIDToTypeID('Lyr '), id);
desc1.putReference(charIDToTypeID('null'), ref1);
if (add) desc1.putEnumerated(stringIDToTypeID("selectionModifier"), stringIDToTypeID("selectionModifierType"), stringIDToTypeID("addToSelection"));
executeAction(charIDToTypeID('slct'), desc1, DialogModes.NO);
} // end of selectByID()
It will, however, add the background (if included). I'm sure you can get around that.

Related

Finding if an event is in a calendar, and if not, making a new event

I'm making an app that adds events to a calendar from a spreadsheet, and then updates the events if the spreadsheet changes. Right now, my code just deletes all the existing events and adds a new one for every entry in the spreadsheet, but sometimes my code errors out because that means I'm adding and deleting too many calendar entries. (Yes, I'm using the sleep utility. Sometimes it crashes anyway.)
It seems like a more efficient way to do this would be to check if the event already exists; if it does, update any changes in the date; and if it doesn't, then create a new event. But I can't quite get my head around how to loop the two lists over each other. If I tell it to loop over all events in the spreadsheet, and inside that to loop over each event in the calendar to look for a match, and if there's no match to make a new event, it seems like it will create a new event for every non-matching item that exists in the calendar for every row of the spreadsheet.
Here's the basic code:
function UpdatePrintCalendar() {
SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/16U6am5GvgWxh0gcRS8FWf9ws7BxaiJU5KOnSo7kOUlg/edit?usp=sharing&key=AIzaSyBe4KN8M-HhMUbN0UcAao7Xm4rIMgOOC6g")
.getSheetByName("PD Hed List").sort(3).sort(4);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var cols = sheet.getLastColumn();
var endofthings = sheet.getLastRow();
var stories = sheet.getRange(1,1, endofthings, cols).getValues();
var rownum = stories.length
var printCal = CalendarApp.getCalendarById("4d1aq2jtt795hfemn7i76cfi30#group.calendar.google.com");
var fromDate = new Date(2019,11,1,0,0,0);
var toDate = new Date(2020,3,31,0,0,0);
var events = printCal.getEvents(fromDate, toDate);
for(var i=0; i<events.length;i++){ /* Clear the calendar. This prevents duplicates. */
var ev = events[i];
ev.deleteEvent();
}
for (x=0; x<stories.length; x++) {
if (x % 10 == 0) { Utilities.sleep(3000); }
var story = stories[x];
var onlinedate = story[1];
var printdate = story[2];
var section = story[5];
var slug = story[6];
var hed = {
'location': section,
'description': slug,
}
if (Boolean(printdate)) {
if (slug) {
printCal.createAllDayEvent(slug, new Date(printdate));
}
}
}
}
}
You can try Array.prototype.filter()
Take a look how to use it on example1 and example2
What I would do in your case:
list all calendar events
find id and title
list titles in Spreadsheet
find what is not match
add missing calendar events
update spreadsheet.

Google Apps Script - XML Parser - Regex

I am using a Google Apps Script that pulls the content from a feed in a sheet.
This is the code that I'm using:
function processXML(FeedURL,sheetsFileDestinationURL,rawPasteSheetName,OPT_childNamesArray,OPT_Namespace){
var OPT_childNamesArray = ["link"]; // get only item url from the feed
var GoogleSheetsFile = SpreadsheetApp.openByUrl(sheetsFileDestinationURL);
var GoogleSheetsPastePage = GoogleSheetsFile.getSheetByName(rawPasteSheetName);
if (OPT_childNamesArray){
GoogleSheetsPastePage.getDataRange().offset(1,0).clearContent(); // get all filled cells, omitting the header row, and clear content
}
else {
GoogleSheetsPastePage.getDataRange().offset(0,0).clearContent(); // get all filled cells, INCLUDING the header row, and clear content
}
// Generate 2d/md array / rows export based on requested columns and feed
var exportRows = []; // hold all the rows that are generated to be pasted into the sheet
var XMLFeedURL = FeedURL;
var feedContent = UrlFetchApp.fetch(XMLFeedURL).getContentText(); // get the full feed content
var feedItems = XmlService.parse(feedContent).getRootElement().getChild('channel').getChildren('item'); // get all items in the feed
for (var x=0; x<feedItems.length; x++){
// Iterate through items in the XML/RSS feed
var currentFeedItem = feedItems[x];
var singleItemArray = []; // use to hold all the values for this single item/row
// Parse for specific children (requires names and namespace)
if (OPT_childNamesArray){
for (var y=0; y<OPT_childNamesArray.length; y++){
// Iterate through requested children by name and fill rows
var currentChildName = OPT_childNamesArray[y];
if (OPT_Namespace){
if (currentFeedItem.getChild(OPT_childNamesArray[y],OPT_Namespace)){
singleItemArray.push(currentFeedItem.getChildText(OPT_childNamesArray[y],OPT_Namespace));
}
else {
singleItemArray.push("null");
}
}
else {
if (currentFeedItem.getChild(OPT_childNamesArray[y])){
singleItemArray.push(currentFeedItem.getChildText(OPT_childNamesArray[y]));
}
else {
singleItemArray.push("null");
}
}
}
exportRows.push(singleItemArray);
}
// Parse for ALL children, does not require knowing names or namespace
else if (!OPT_childNamesArray){
var allChildren = currentFeedItem.getChildren();
if (x == 0){
// if looking at first item, create a header row first with column headings
var headerRow = [];
for (var h=0; h<allChildren.length; h++){
headerRow.push(allChildren[h].getName());
}
exportRows.push(headerRow);
}
for (var c=0; c<allChildren.length; c++){
singleItemArray.push(allChildren[c].getText());
}
exportRows.push(singleItemArray);
}
}
// Paste the generated md array export into the spreadsheet
if (OPT_childNamesArray){
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValues(exportRows);
}
else if (!OPT_childNamesArray){
var maxRangeLength = 0;
var currentRowIndex = 1;
for (var x = 0; x<exportRows.length; x++){
if (exportRows[x].length > maxRangeLength){
maxRangeLength = exportRows[x].length;
}
GoogleSheetsPastePage.getRange(currentRowIndex,1,1,exportRows[x].length).setValues([exportRows[x]]);
currentRowIndex++;
}
}
}
My problem is this:
When I run this code I get:
https://url/115-396/
https://url/115-396/
https://url/115-396/
I need to remove "115-396/".
So I tryed to add this code but didn't work:
...
// Paste the generated md array export into the spreadsheet
if (OPT_childNamesArray){
for (var k = 0; k < exportRows.length; k++) {
var re = '115-396/'
var replacingItem = '';
var URL = exportRows[0].toString().replace(re, replacingItem);
}
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValue(URL);
}
else if (!OPT_childNamesArray){
...
Edit after #Yuri reply:
// Paste the generated md array export into the spreadsheet
if (OPT_childNamesArray){
for ( k=0; k < exportRows[0].length; k++) {
var re = '115-396/'
var replacingItem = '';
exportRows[0][k] = exportRows[0][k].toString().replace(re, replacingItem);
}
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValues(exportRows);
}
result:
https://url/
https://url/115-396/
https://url/115-396/
Basically, the regex is applied only to the first url.
How I can make that the regex is applied to all the url's?
Any help?
Thanks
You are using a for to iterate thru the exportRow array, but later on, you're not using the k iterator inside the for.
Then, you are not accessing the exportRows array, only the first position:
var URL = exportRows[0].toString().replace(re, replacingItem);
Shouldn't be?
var URL = exportRows[k].toString().replace(re, replacingItem);
In that case, it won't work, because URL it's not an array, so by doing this you are only saving the last assignation produced on the for iterator on the URL, I believe you are trying to do the following:
for ( k=0; k < exportRows.length; k++) {
var re = '115-396/'
var replacingItem = '';
exportRows[k] = exportRows[k].toString().replace(re, replacingItem);
}
And you'll have exportRows as an array of the desired url's without the 115-396 extensions.
Now you can place this on the spreadsheet with setValue as you were doing, but setValue is for strings, integers, etc, and not for arrays. For arrays you have setValues()
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValues(exportRows);
But, then, the range of exportRows should match the range of your getRange selection, which I'm not sure it's happening.
Just to clarify it, exportRows.length is the length of the array, and exportRows[1] is the length of the string/url stored on the position 1 of the array.
Hope this helps, the question is not really clear neither the intentions, provide more info if still not working.
How to know the size of the range you're getting?
var myrange = GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length)
Logger.log(myrange.getNumRows());
Logger.log(myrange.getNumColumns());
You'll be able to know the range you have on getRange and make it match with the exportRows size.
Make sure to check the attached documentation, and in case you have more doubts please open a new question related to it.

InDesign Export all TextFrames to JPG or PNG Individually

I'm struggling with a problem where I need to get JPGs of all the written questions in InDesign since I work at a school. To make the process faster, I decided to go the "Export Objects" way. But i couldn't find a suitable script to achieve what I need.
Basically,
Select All Text Frames in the given Layout(Alternates are present)
Export All Text frames as JPG with given DPI value and name variable.
Both actions are actually available with the Sample codes, but in a different way. For example: SelectObject script works, but when combined with Command+E, the export result is one big image that contains all the selected frames. I want them separately.
I've tried combining the scripts given as applescript or js with my little knowledge of coding but no cigar.
Select Text : Indesign CC 2018 - SelectObjects Sample Code.
Image export: Indesign CC 2018 - Export to JPG scripts are the codes I've tried mingling with.
Goal: Export all text frames individually as variable DPI, variable name and variable destination from separate alternate layouts.
Edit 1: Code that I'm trying to mingle with. I found it on reddit but even though it essentially does what i need, it does in a crooked way and unusable. IT exports ALL items and they are with the page background, I'd need only the stuff that are contained within the TextFrame.
// Set resolution options
var rp = [72,150,300];
// Set EXPORT presets
app.pngExportPreferences.exportResolution = 72;
app.pngExportPreferences.antiAlias = true;
app.pngExportPreferences.pngQuality = PNGQualityEnum.MAXIMUM;
app.pngExportPreferences.pngColorSpace = PNGColorSpaceEnum.RGB;
app.pngExportPreferences.pngExportRange = PNGExportRangeEnum.EXPORT_RANGE;
// Resolution Select Dialog
var w;
w = new Window('dialog', 'Export Presets');
w.orientation = 'row';
with (w)
{
w.sText = add('statictext', undefined, 'Select Export Resolution:');
w.dropdown = add ( 'DropDownList',undefined,undefined,{items:rp});
w.btnOK = add('button', undefined, 'OK');
};
w.dropdown.selection=0;
w.show();
// Set resolution
var x = 0;
x = x + w.dropdown.selection;
app.pngExportPreferences.exportResolution = rp[x];
// SElECT Folder locations
var myFileAmount = 0;
var myFileLocation = Folder.selectDialog("Please select path of InDesign Files");
myFolder = new Folder ([myFileLocation]);
myFolderContents = myFolder.getFiles("*.indd"); // array
myFileAmount = (myFolderContents.length - 1);
// CHECK IF FILES IN FOLDER
if (myFileAmount < 0){alert("No Files in selected folder");}
else
{
var mySaveLocation = Folder.selectDialog("Please select path to Save PNG");
mySaveFolder = new Folder ([mySaveLocation]);
// OPEN FILES One at a time
for (i = myFileAmount; i >= 0; i--)
{
app.open(File (myFolderContents[i]));
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.NEVER_INTERACT;
// SET Active Document
var myDoc = app.activeDocument;
// EXPORT
//One Page at a time
for (var p=0; p < myDoc.pages.length; p++)
{//page loop
var pname = myDoc.pages.item(p).name;
//set all items in file hiden
for (var itemnum=0;itemnum < myDoc.pages.item(p).pageItems.length; itemnum++)
{
myDoc.pages.item(p).pageItems.item(itemnum).visible = false;
}
// set page to export
app.pngExportPreferences.pageString = pname;
//add a 0 in from on less than 10
if (p<9){var pnm=0;}else{var pnm=""}
//LOOP Through items Set Visibility, export a PNG, Set Visibility
for (var itemexport=0;itemexport < myDoc.pages.item(p).pageItems.length; itemexport++)
{
var itm = itemexport+1;//items start at 1 not 0
myDoc.pages.item(p).pageItems.item(itemexport).visible = true;
//ACTUALLY EXPORTING
app.activeDocument.exportFile(
ExportFormat.PNG_FORMAT,
File(mySaveFolder.fsName + "/" + app.activeDocument.name.split(".indd")[0] + "_"+ pnm + pname + "_" + itm +".png"),
false,
);
//SET VISIBILITY
myDoc.pages.item(p).pageItems.item(itemexport).visible = false;
}
}
app.activeDocument.close(SaveOptions.no);
}
}

InDesign javascript Master Page item override doesn't work

I can't get a Master page item override working.
In the code what should I put as destinationPage?
Currently, I keep getting an error message "Invalid object for this request"
var myDoc = app.activeDocument;
var myPages=myDoc.pages;
var myItems = myDoc.pages[0].appliedMaster.allPageItems;
for (y=0; y<myItems.length; y++){
if(myItems[y] instanceof TextBox){ //&& myItems[y] instanceof TextBox ){
myItems[y].override(myPages[0]); //This bit doesn't work. What do I put here as destinationPage?
}
}
Thanks
I'm going to make a few assumptions here about what you are trying to achieve. I'm assuming that you are looking to override all of the TextFrames on the first page of your document.
var myDoc = app.activeDocument;
var myPages = myDoc.pages;
var myMasterPage = myPages[0].appliedMaster.pages[0]; // assuming single pages
var myItems = myPages[0].allPageItems; // assuming you want to override the items on the first page
for (y=0; y<myItems.length; y++) {
var myItem = myItems[y];
if (myItem.constructor === TextFrame) { // assuming you meant TextFrame instead of TextBox
myItem.override(myMasterPage);
}
}

How to save a HTMLElement (Table) in localStorage?

I've been trying this for a while now and could not find anything online...
I have a project, where tablerows get added to a table. Works fine.
Now I want to save the Table in the localStorage, so I can load it again. (overwrite the existing table).
function saveProject(){
//TODO: Implement Save functionality
var projects = [];
projects.push($('#tubes table')[0].innerHTML);
localStorage.setItem('projects', projects);
//console.log(localStorage.getItem('projects'));
The problem is the Array "projects" has (after one save) 2000+ elements. But all I want is the whole table to be saved to the first (or appending later) index.
In the end I want the different Saves to be listed on a Option element:
function loadSaveStates(){
alert('loading saved states...');
var projects = localStorage.getItem('projects');
select = document.getElementById('selectSave'); //my Dropdown
var length = projects.length,
element = null;
console.log(length);
for (var i = 0; i < length; i++) {
element = projects[i];
var opt = document.createElement('option');
opt.value = i;
opt.innerHTML = 'project ' + i;
select.appendChild(opt);
}
}
Can anyone tell me what I am doing wrong?
You can easily do this by jquery, are you interested in this, if yes.. then try following code
For setting the value
$.jStorage.set("projects", $.trim(projects));
For Getting the data
$.jStorage.get("projects");
For deleting the data with key
$.jStorage.deleteKey("projects");
I coose to stay with localStorage, but insted of using an Array I just let the user give every project a name and create a new Item for every Save:
function saveProject(){
//TODO: Implement Save functionality
var pname=prompt("Please enter your project name:","projectname")
var text = $('#mainTable')[0].innerHTML;
//console.log(text);
localStorage.setItem(pname, text);
//console.log(localStorage.key(2));
loadSaveStates();
}
function loadProject(){
var selected = $('#selectSave')[0].selectedIndex
//console.log(selected);
if (localStorage.key(selected) == 'jStorage'){
selected++;
}
var innerHTMLTable = localStorage[localStorage.key(selected)];
//console.log(innerHTMLTable);
$('#mainTable')[0].innerHTML = innerHTMLTable;
updateHandlers();
}
function deleteProject(){
var selected = $('#selectSave')[0].selectedIndex
var pname = $('#selectSave')[0].options[selected].value
$('#selectSave')[0].remove(selected);
localStorage.removeItem(pname);
//console.log(pname);
loadSaveStates();
}

Categories