Create a Calendar Using Scripting in Photoshop
Tutorial Details
- Program: Adobe Photoshop CS4
- Difficulty: Intermediate
- Estimated Completion Time: 1 Hour
- Adobe ExtendScript Toolkit CS4 (optional)
Download Source Files
Final Product What You'll Be Creating
Creating a graphic calendar by hand is not an easy task. That is why it is best if you can find some way of automating the process. In today’s tutorial we will show you how to generate a full year, custom background calendar using JavaScript. If you’re a bit of a computer programmer, that is great, if not, don’t worry this will be pretty straightforward.
Step 1
According to Adobe, a script is a series of commands that tells Photoshop to perform one or more tasks. The first thing you need to do is take a look at Adobe’s JavaScript Reference. You can find it here. This contains all the object properties and methods Photoshop CS4 supports, with examples, and it will give you an idea on what kind of things you can do with scripting in Photoshop. If you are using an older version you can find references here.
Step 2
So let’s get started. The main idea for the project is to create text layers for each month containing the dates, so we will be working mainly with text manipulation. Open ExtendScript Toolkit and create a new JavaScript file (Command+N). This will contain all the commands we are going to give Photoshop. If you don’t want to use ExtendScript Toolkit, you can use any simple text editor.
Step 3
First we have to define some variables for the document attributes and the calendar color scheme. I made my document 1280×800 at 72 pixels/inch resolution, named it "PhotoshopScriptCalendar" and chose 2010 as the year of the calendar we will create.

This is the basic color scheme we are going to use. "NormalColor" is for weekdays and month names. For Sundays I used a different color in order to make them stand out, this is "highlightColor", and we’ll be using "backColor" as the default calendar background color if we do not select a custom image for that.

Step 4
As I said before, we are mainly going to work with text manipulation, so we must define some variables for the indentation and text that we are going to use repeatedly, like the month headers.

In order to set a different color to the Sundays column, we have to make it a different text layer from the other days. This is why we have two headers: "monthHeader" – Monday to Saturday, and "sundayHeader". Each of these two variables end with two "\r". These stand for new line characters, the same as pressing the Return key on your keyboard. Next we define the indentation variable. Notice that the first of January is a Friday, so for each day before that we must put an indent instead of numbers. The number of whitespaces of these variables depend on the font you use and the size of it, so it will need a little bit of trail and error before you get it right. Finally, make a list of all the month names.

Step 5
Now that we have every thing we need, we can start creating the .psd document.

As you can see, the code is fairly readable. To our Photoshop application, we add a new document with the specified width, height, resolution, and name we defined earlier, a color mode, and retain its reference in a new variable "doc". By default all new documents are in RGB, so we could have omitted that parameter, but if you want CMYK for example, you could use "NewDocumentMode.CMYK". The same with LAB, GRAYSCALE and BITMAP. You can find all of these in the references linked above.
Next we make a new selection and select the entire document, fill it with our background color, and eventually deselect it.
Step 6
Next we need to add a custom background from an existing image. The gradient background from the final result posted above is actually a separate image.

For this we are going to use the openDialog() function. This opens the dialog from "File > Open" and puts in the array "file" the list of selected images. We are going to use only the first selected image which is in the "file" array at position 0. So, first we need to check if any image was selected.

Next, we are going to load the selected image in our application and get a reference to it by calling "app.activeDocument" which returns the currently active document in Photoshop.

Resize the image to our preferred width and height. Again, we make a new selection of the whole document, copy this selection and close the document with the option of not saving the changes.

Finally, in our calendar document, paste the selection. This puts the image as the first layer above the Background layer. Then name it something like "BackgroundImage".
Notice that if no image was selected from the dialog, none of these commands would have been done.

Step 7
OK. Now comes the actual generation of the calendar. This could be a little more difficult, but we’ll take it step by step and hopefully it won’t be that hard to understand.
We need to do a set of actions for each month of the year. For this we use a "for" loop. Basically, this takes the variable "curr", which we use to denote the current month we are working with, sets its initial value to 0, then does the set of actions repeatedly, incrementing the value of "curr" each time, until this becomes 12. Thus going through all twelve months.

First we must define two variables we are going to use to position our months in the document as a grid. These represent the X and Y offsets of each month. We are going to put 4 months on a single row, so for the X offset we are going to use the "%" operation. This returns the remainder of the division of "curr" to 4. This offset is going to be the same for January, May, September, for February, June, October, and so on, for every month in the same column. For the Y offset we use the "Math.floor()" javascript function that returns the largest value, smaller than the division result of "curr" to 4. Thus for the months from the same row, the Y offset is the same.

In the end we want to have the layers for each month in a separate group. So we are going to start off by creating a layer group and giving it the name of the current month. We use here the list of months we defined earlier.

Step 8
Next we create a new text layer inside our group and set its name to the current month. This is going to be our month name layer.

Now we have to set the text attributes such as text color, font size, and justification. We are going to set the type of our text to "PARAGRAPHTEXT" and give our layer the preferred dimensions. The "contents" attribute of the "monthName" variable stands for the actual text that will be visible inside the layer, so we want this to be the name of the current month.

Finally we are going to rotate the layer 90° counter-clockwise and position our layer. Here we are going to use our offset variables "x" and "y".

Please keep in mind that the positioning is done relative to the layers’ top left corner, but since we’ve rotated the it 90° CCW it now has become bottom left corner. If your document has different dimensions from mine, you may need to change the constants I used for positioning. The values I used are listed below.

Step 9
Next we are going to make the text layer that will contain all the dates in the current month, except the Sundays. We are going to add it to the group we created earlier and set its name, justification, font color and size, and position it. We are going to add the content of this a little bit later, I’ll explain why, when we get to that point.

Same thing for the Sundays layer, but this time we are going to set the color to "highlightColor".

Step 10
Now, we need to create two variables that will hold our text as we generate it, "text" will contain the weekdays and "textSun" the Sundays. We start of by adding the headers and putting the indent for the first of the month. We create a new date with the javascript "Date()" function from the year of our calendar, the current month and the first of that month, and get its position in the week. Remember, the numbering always starts from 0, so for example if the first of the month is a Monday, "n" will be 0, if it is a Tuesday, "n" will be 1 and so on. Then we need to add the indent we defined at the beginning to our "text" variable as many times as needed. If the first of the month is a Wednesday for example, we’ll add the indent two times.

Step 11
OK. It’s time to generate all the numbers for the month. For this we need to know how many days there are in our current month and we need the numbers in "leading zeros" format, so we must go back and define two custom functions: "daysInMonth" and "makeDay". So please scroll up to the top of your code and add these functions. As I said the "daysInMonth" function returns the number of days in the month we give it, and "makeDay" returns the number we give it in a specific format and adds some whitespace, necessary for spacing the days of the month. So, for example if we call the "daysInMonth" function with the year = 2010 and the month = 0 (January) it will return the number 31. If we call the "makeDay" function with d = 3 for example, it will return the text "03 ", but if d = 13 it will return "13 ". Notice that if "d" is less than 10 it will add a zero before it.

We are going to start from d = 1 and increment it until it reaches the number of days in the month. Now, if "i" has the value "6" it means that it is a Sunday, so we have to add it to the Sunday layer. Remember to put an "\r" here for new line. Otherwise, we add it to the weekdays. Here we add a new line only if the current day is "Saturday" ("i" is "5"). At the end, we have to increment both "i" and "d", and if the value of "i" reaches "7", that is if the last day added was a Sunday, we have to make it "0" again.

Finally, we have all the dates in our text variables and we can add them to our layers. The reason we have delayed this step is that it takes some time for Photoshop to add text to a layer, so it’s better to add it all at once, rather than add each day separately.

Step 12
So, all the month layers are now generated, and all we need to do is to make the year layer, and that little line at the bottom. For the year layer it’s the same procedure we used before, create a new layer, give it a name, text size and color, and position it where we want.

For the bottom line it is a bit different. First we must define a region with X and Y coordinates for all four corners, then make a selection out of that region, fill it with our color on a new layer and finally deselect it.

Step 13
All our code is done! The only thing to do now is to run it. If you are using ExtendScript Toolkit, from the drop down menu select "Adobe Photoshop", if you do not have Photoshop opened, click on the little icon on the left "Connect to target application", and then press the play icon. If you’ve used a different text editor, save the file with the ".js" or ".jsx" extensions, and run it from Photoshop: File > Scripts > Browse and then select your file.
Conclusion
We are finished! Hope you’ve enjoyed working on this little project. Scripts in Photoshop are very useful when having to do repetitive actions and can make your job a whole lot easier once you get the hang of them. Please do not hesitate to send any suggestions you may have, they are always welcomed!




very nice working thanks for tutotial
This is pretty much fantastic! I’ve never seen this technique, very interesting!
Wow~. Its very useful. Thanks a lot
Well done. Please post the whole code at the end next time, so we dont need to go piece for piece thru the code.
here is the code, all put together. if i made any mistakes, sorry.
// DEFINE AUXILIARY FUNCTIONS
function daysInMonth(month, year){
return 32 – new Date(year, month, 32).getDate();
}
function makeDay(d){
if(d < 10)
d = "0" + d;
return d + " ";
}
// DOC. ATTRIBUTES
width = 1280;
height = 800;
resolution = 72;
docName = "PhotoshopScriptCalendar";
year = 2010;
// COLOR SCHEME
normalColor = new SolidColor();
normalColor.rgb.hexValue = "FFFFFF";
highlightColor = new SolidColor();
highlightColor.rgb.hexValue = "A4B1D1";
backColor = new SolidColor();
backColor.rgb.hexValue = "1B4392";
// DEFINE VARIABLES FOR TEXT LAYERS
monthHeader = "M T W T F S \r\r";
sundayHeader = "S\r\r";
firstIndent = " ";
months = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
// CREATE THE NEW DOCUMENT
doc = app.documents.add(width, height, resolution,
docName, NewDocumentMode.RGB);
doc.selection.selectAll();
doc.selection.fill(backColor);
doc.selection.deselect();
// SELECT BACKGROUNDIMAGE
file = app.openDialog();
if(file[0]){
app.load(file[0]);
backFile = app.activeDocument;
backFile.resizeImage(width, height);
backFile.selection.selectAll();
backFile.selection.copy();
backFile.close(SaveOptions.DONOTSAVECHANGES);
doc.paste();
doc.layers[0].name = "BackgroundImage";
}
for(curr=0; curr<12; curr++){
x = curr % 4;
y= Math.floor(curr / 4);
group = doc.layerSets.add();
group.name = months[curr];
monthName = group.artLayers.add();
monthName.kind = LayerKind.TEXT;
monthName.name = months[curr];
monthName.textItem.color = normalColor;
monthName.textItem.size = 24;
monthName.textItem.kind = TextType.PARAGRAPHTEXT;
monthName.textItem.justification = Justification.RIGHT;
monthName.textItem.height = 35;
monthName.textItem.width = 145;
monthName.textItem.contents = months[curr];
monthName.rotate(-90);
monthName.textItem.position = new Array(55 + 300 * x, (202 + (210 * y)));
days = group.artLayers.add();
days.kind = LayerKind.TEXT;
days.name = "Days";
days.textItem.Justification = Justification.CENTER;
days.textItem.color = normalColor;
days.textItem.size = 18;
days.textItem.position = new Array(85 + (300 * x), 70 + (210 * y));
sundays = group.artLayers.add()
sundays.kind = LayerKind.TEXT;
sundays.name = "Sundays";
sundays.textItem.Justification = Justification.CENTER;
sundays.textItem.color = highlightColor;
sundays.textItem.size = 18;
sundays.textItem.position = new Array(287 + (300 * x), 70 + (210 * y));
text = monthHeader;
textSun = sundayHeader;
startDate = new Date(year, curr, 1);
n = startDate.getDay();
for(i=0; i<n-1; i++)
text += firstIndent;
d = 1;
while(d <= daysInMonth(curr, year)){
if(i == 6)
textSun += makeDay(d) + "\r";
else{
text += makeDay(d);
if(i == 5)
text += "\r";
}
i++;
d++;
if(i == 7)
i = 0;
}
days.textItem.contents = text;
sundays.textItem.contents = textSun;
}
// CREATE THE YEAR NUMBER LAYER
yearLayer = doc.artLayers.add();
yearLayer.kind = LayerKind.TEXT;
yearLayer.name = year;
yearLayer.textItem.contents = year;
yearLayer.textItem.size = 72;
yearLayer.textItem.color = highlightColor;
yearLayer.textItem.position = new Array(1050, 730);
// CREATE THE BOTTOM LINE
line = doc.artLayers.add();
line.name = "Line";
region = Array(Array(80, 729), Array(1000, 729), Array(1000, 730), Array(80, 730));
doc.selection.select(region);
doc.selection.fill(normalColor)
doc.selection.deselect();
monthHeader = “M T W T F S \r\r”;
sundayHeader = ” S\r\r”;
firstIndent = ” “;
sorry bout that. the lines right below the DEFINE VARIABLES FOR TEXT LAYERS, my code was wrong there. the right code is above
its lines 32-34 btw
wow, great! Didn’t realize you could do this. Useful tip that makes me want to dig deeper.
This is Brilliant… Very useful. I have searched a lot for something like this…
Cheers..
I would probably never do something like this, but I’m amazed that it’s even possible.
Very well done.
Great and exceptional tut !
Exceptional was the word i was looking for.
Wow. I didn’t even know Photoshop had JavaScript scripts support. Great article, thanks!
Well done, but some parts of the screenshots weren’t clear as far as placement goes. Please post the source code.
its broken, not working at all
I had absolutely no idea you could do this kind of thing in Photoshop. I’m amazed! I can’t wait to give this one a try.
Wow me too, i can’t wait
Hey very nice. That’s the very first time I see a tutorial (other than sdk) on how to write a js script with ESTK.
Congrats for your effort.
May I invite you to drop an eye on our scripts library for Adobe Desktop Publishing Software ? http://www.scriptopedia.org
Hope I see u there.
Loic
what?! this is photoshop! damn, i had no idea… (of course i knew it was a psd tutorial, but i had no clue you could do THIS in PS… pretty cool, but out of my league… ill stick with indesign)
nice but useless…
the time i need to code this whole beast… i would have built you 3 of these calendars.
thats a fact… but nice to see another how to get a clean finish…
Me too, not so useful in this instance…
… however … there are probably some good uses for this, so it is certainly interesting to know that you can do this sort of thing.
great! offering new possibilites
Waaa!? I had no clue you could do this in Photoshop I would have done in AS. Great work!
This is amazing, but like people said, is basically useless to me. I’d just make it by hand, because coding that would be a huge pain for me.
Whooa
What is this? I’ve heard about this script in Photoshop but I never expect that its going to be this far. You even fill color and draw line using script!
Awesome tutorial.
Don’t be sarcastic
I even didn’t know that you could use scripts in Photoshop. Wondering what else you can do whit coding in PS?
hmmmmmmmm
i’m just wordless .. is it Photoshop? well tutorial is awesome.. but it’s to exiting news new we’ve to work dynamically ..
This is such an amazing technique! Have never thought PS can be used in this manner. Thanks so much for the info pal.
OMG. Code everywhere. Please, no code in Photoshop too.
i’m having trouble with the creation of the doc
doc = app.documents.add(width, height, resolution, docName, NewDocumentMode.RGB);
says this functionality may not be avaliable in this version of Photoshop.
i have CS4 11.0.1 version =o
any clues?
i’m getting CM insted of pixels, how do i fix this?
thankss!
Same problem. Please, do anyone know how to fix?
got o edit > preferences > units & rulers
Not woring at all. Debug problem at lines 28-31.
Thanks for this tutorial! really wondered!
Wow! Thanks for the tutorial–I used scripts in Photoshop every other day, but I had no idea how to write them myself. This is seriously useful!
looks good…definitely gonna try this
Please post the end code.
I completed the tutorial and the placement of some of the days are wrong.
Also, in the bottom of Step 8, it shows the monthName position to be
monthName.textItem.position = new Array(55+300*x, (202+(210*y)));
but in Step 9, it shows monthName position to be
monthName.textItem.position = new Array(300*x, 130+(210*y));
please clarify
This is something I didn’t know, gonna try it!!! 5 years of computer sciences studies will become really handy
lol guys, you all are experts in Photoshop but i’m really shocked to know that many of you don’t know that Adobe CS supports Javascript? very strange..
Hey, nice TUT, but i think it doesnt works…
The code have a lot of errors, and i changed it like, 4 times?, maybe this is like “Buy our subscription” or something??
Very, very shameful
Paste the code.
its posted above
I have it running now – will let you know if it worked for me. This is my first time with a script and I find it so interesting. Something more for me to learn in PS. LOL
Thanks for sharing. If you have any other PS scripts I hope you will share them as well.
Wow. Great tutorial! Learned something new today
In fact it`s – somehow – hard to produce .
a lot of steps
but thanx any way
Great Tut. I have never tried this before, will definitely give it a shot!
Very Good. Thanks.
amazing techniques for create calendar using Photoshop.
Nice tutorial, gave it a shot last night, awesome calendar generated with professional look, might seem a little odd to pure designers but for programmers like me , this is really great stuff done with scripting, guys don’t worry about the code, its simple as far as i know, please ensure that you have proper Tab settings in your texteditor for proper day and date alignments…
I didn’t know you could do scripts in Photoshop like that.
Thanks!
For something like this, a one-off design, the scripting isn’t as useful. But the idea is that scripting can be extremely useful for batch creation/processing of images. Very cool tutorial indeed.
Scripts in PHOTOSHOP that’s the evolution
WOW, that is awesome. Never knew about these types of scripts used in PS. Thank you for sharing.
Nice Tutorial
but look at the result you will find a wrong day display in August…..Starting with the Sunday dispayed as Monday
I guess there is a little bug left
best regards
Thanks for the post! This is something new to share with everybody! Thanks for sharing mate!
This is a very good tutorial and I didn’t think anything like this was possible in Photoshop. However the if a month begins on Sunday, like August, it will render as if it was on began on Monday. Days in JavaScript are labelled 0 for Sunday, 1 for Monday, 2 for Tuesday etc, so I think that’s where the error came from. I made some changes to fix this:
for(i=0; i<n-1; i++)
text += firstIndent;
//CHANGES START HERE
if(n == 0)
i = 6;
d = 1;
while(d <= daysInMonth(curr, year)){
if(i == 6){
textSun += makeDay(d) + "\r";
text += "\r";
}
else{
text += makeDay(d);
}
//CHANGES END HERE
i++;
d++;
if(i == 7)
i = 0;
}
Dude. If you don’t post the source code at the end; completed with no errors, you are useless. I hate to be so brutal but c’mon now! I’m not a commenter on blogs. I usually read them and keep my comments to myself. You get no punk rock points today… and for all the commenters… you get no punk rock points either! I’ve copied and pasted your code and it doesn’t work. I’ve spent an additional hour looking through the comments for fixes and none of those work. This was a waste of 3 hours. So…. thank you for that.
Stop moaning, it’s a free tutorial, and others have obviously got a lot of value from it
Worked like a dream. The full code that Axel posted (and the edit) worked great once you make sure that the correct “” are used everywhere and that the – is the right one. Thanks for saving me from typing it out.
Nice tute
just create a calendar with adobe indesign scripts or illustrator and paste into photoshop. much easier.
Excellent!
You open new horizon for me. I was struggling at beginning by following your steps given in image; I got text version so much helpful.
Error in here:
while(d <= daysInMonth(curr, year)){