Array Formulas

Document Sample
Array Formulas Powered By Docstoc
					Using Array Formulas in Excel OFC-10
What Are Array Formulas?
Imagine being able to tell via a formula if your data is correct, such as determining that
the successive cells increase by 1, or whether 2 ranges have duplicate values. Can you
determine in one formula if your text matches a particular pattern in an entire range (like
First name, space, Last name?) and if not, point to the cell with the error?
How often did you wish you could easily know, from a list, the total of amounts with
year 1995 for department "Finance", when that list is strewn with dates other than 1995
and departments other than Finance? Array-formulas come to the rescue. Want to sum the
digits in a cell? Try it. It needs an array formula (enter 81736 in a cell and by some
formula come up with the value 8+1+7+3+6). Again, this technique is solved with array
Array formulas are very powerful formulas which can summarize data on a worksheet or
even summarize data which is not on a worksheet (like being able to determine the total
amount for items in March when the range consists of dates, not just months, for
example. Whoever uses MONTH(A1:A50)?).
They are always entered via holding the Ctrl and Shift keys before pressing enter. Doing
so places curly braces {} around the formula, but only in the formula bar. You do not
enter these. They are best explained by examples.

Using The OR Function
This technique isn’t an array-function, and shouldn’t be array-entered, but it should be
included because it deals with array-constants in a way you might not be aware. Suppose
you have a cell, B1, which you want to test for it containing either a 4, 6, or 9. You might
be tempted to enter =OR(B1=4,B1=6,B1=9) which would work fine, but there’s an easier
way. The formula =OR(B1={4,6,9}) does the trick.
The curly braces were entered (manually) to indicate an array constant. When entering an
array constant you cannot enter variables even though their values might be known. That
is, if x is defined to be =4, then you still couldn’t use =OR(B1={x,6,9}) -- you would get
“error in formula.”

Finding The Bottommost Cell In A Range
This technique works for both single column ranges or multiple column (but contiguous)
ranges. Often, the bottommost cell of a contiguous range of cells is not necessarily the
last cell in that range. You may have A1:A20, then A30:A35 filled. The bottommost cell
is A35. Let’s look at a range of cells from A1:E10.
To find the last-used cell in the range you can array-enter
=MAX(ROW(1:10)*(A1:E10<>"")). The part, A1:E10<>"" will return a 10x5 array of
TRUE/FALSE values. This comparison could also have been done using ISBLANK
function: NOT(ISBLANK(A1:E10)). FALSE means the cell is blank, TRUE means the cell
has some value. By multiplying this array by the values {1;2;3;...;9;10}, which is done by
using ROW(1:10), you get
Notice the semi-colons after every 5 values, corresponding to the “next row” in the
evaluation. The zeros are the result of multiplying FALSE by any number. If you visually
scan the expansion of the array, you see the first non-zero is a 3. This is in the third “row”
of values, in the “set” {0,0,0,3,0}. This corresponds to cell D3 in the range A1:E10. The
3 is the result of multiplying TRUE by the corresponding position of the ROW(1:10) --
we’re in the third “row”, and TRUE multiplied by 3 is 3. Every non-zero corresponds to a
non-blanksin the range. This array is passed to the MAX function, which in this case
returns a 9, giving the desired result: 9 means the bottommost row used in A1:E10 was 9.
Searching Strings For Errors across ranges.
Suppose cells A1:A10 are supposed to contain names in the form First name, space, Last
name. Also suppose that cells A7 and A9 have errors -- there are no spaces between the
first and last names. (Like BillClinton).

                                                       This technique explores a way to
determine which names, if any, are in error. Let B2 contain the formula
=IF(NOT(ISERROR(B1)),INDEX(A1:A10,B1)&" is incorrect.","") which says that
if cell B1 is not an error, then display the offending cell and the text “ is incorrect.”. The
offending cell is indicated as the INDEX(A1:A10,B1). Therefore, cell B1 must contain
the location of the cell which contains an error within the range A1:A10. Cell B1 contains
the formula =MATCH(TRUE,ISERROR(SEARCH(" ",A1:A10)),0). This is an interesting
formula in that one does not usually use a MATCH(TRUE... in Excel. You will find that this
(as well as MATCH(FALSE...) has very powerful applications. But first, let’s examine the
inner part of the formula: SEARCH(" ",A1:A10) is unusual in that the SEARCH function
usually examines a cell, not a range. Therefore, it’s this usage which requires the formula
being array-entered.
This function might return something like {4;3;5;4;8;8;#VALUE!;6;#VALUE!;6}. The
first value, 4, means that there’s a space in the 4th position of cell A1. Similarly for the 3
and 5. The #VALUE! error in the 7th position of the array corresponds to cell A7, which
contains BillClinton, and indicates there is no space in the cell. Similarly for cell A9. This
array is passed to the ISERROR function which converts the array to
the TRUE corresponds to the #VALUE! errors. The MATCH function, then, finds the
TRUE value in this array, and the value in cell B1, 7 in this case, is the result (the “,0” at
the end of the MATCH function indicating that an exact match is to be found). If all the
cells contained a space, the array would be all FALSE’s, and the MATCH would return
an error. Therefore, cell B2 would be blank because it’s testing for an error condition in
cell B1.

Counting occurrences of substrings in a range of cells
Suppose you wanted to know how many times the letter “a” occurred in a range of cells?
Or how many cells contained an “a”? Each has its own solution. One way to find the
number of cells in a range containing an “a” is to use the formula
=SUM(IF(ISERROR(SEARCH(“a”,MyRange)),,1)). This formula uses the SEARCH
function to search a range of cells. Since usually this function is used to search a string,
not a range, the solution requires you to array-enter the formula. (FIND could be used if
you were interested in a case-sensitive search).The SEARCH will return an array of
numbers or error values. The numbers correspond to the position in the string of the letter
“a” and the errors indicate there’s no “a”. The array corresponds to each cell in the range.
Since it’s not easy to work with error values, the ISERROR converts them to
TRUE/FALSE. Wherever there’s a FALSE, the IF returns a 1. By the way, this formula
could also have been done with =SUM(1*NOT(ISERROR(SEARCH(“a”,MyRange))))
which changes the FALSEs to TRUEs by using the NOT function, then multiplying them
by 1 so the SUM function could add them up.
If you were interested in how many times an “a” occurred, counting “banana” as having 3
a’s, you could use the formula =SUM(LEN(MyRange))-SUM(LEN(SUBSTITUTE(MyRange,
"a",""))). Here’s how this one works. The LEN function usually requires, again, a
string, not a range. So, the requirement is to array-enter the formula so Excel knows to
treat each value in the range as a string for the LEN function. LEN(A1:A2) would return
{3;5} if A1 contained “bob” and A2 contained “Sally”. By taking the
SUM(LEN(MyRange)), we have the total number of characters in MyRange. If we subtract
from that the total characters in MyRange without the letter “a”, then we have the
number of times “a” appears. This is what the second part of the formula does. The
SUBSTITUTE function is changing “a” to the null string. Within a range of cells, each is
returned as an array of values, passed to the LEN function, and SUMmed up.

Finding The Last Part Of A String
It is fairly frequent that you want to know the name of a file without its path, as in the

Cell A1 contains the text of the path to a file. The backslash is used as a delimiter,
separating the various “fields.” Cell A1 could also contain any text, like “Now is the time
for all good men to come to the aid of their party” where the “delimiter” is a space, and
this technique will extract the word “party,” the last “field” in the string. The formula in
cell A3 is complicated, so let’s see what it needs to contain rather than just reveal it.
The task would be easy if we needed to find the first backslash: we could use the
SEARCH function. If the text were reversed, then we could find the first backslash. So,
our job will be to reverse the text. It turns out that reversing the text in one formula is not
possible (or at least I have not discovered a way!), but it is possible to reverse the text as
single characters rather than as one string. For an easier example, suppose cell D7 in a
different spreadsheet contained the text “abc”. How can we change that to the array
{“c”,“b”,“a”}? Well, that can be done fairly easily. Since the technique which makes it
{“a”,“b”,“c”} is by array-entering =MID(D7,ROW(1:3),1), look at what this function
does: =MID(D7,4-ROW(1:3),1). By introducing the “4-”, we are subtracting the array
{1;2;3} from the value 4, which produces the array {3;2;1}! Now, =MID(D7,{3;2;1},1)
produces {“c”,“b”,“a”}.
Now that you see the approach, let’s look a bit further. Instead of using a constant, 4, we
use the LEN(D7)+1. Instead of just reversing the string, we also need to MATCH the
delimiter against this string to find the first one.The formula
MATCH("\",MID(A1,LEN(A1)+1-ROW(1:25),1),0) used in the illustration above
You can see that we’re searching backwards for the occurrence of the backslash. This
evaluates to 8. So, what do we do with this 8? We actually want one less characters from
the end because we don’t want to include the backslash. We need to take the last 7
characters of the cell. That lends itself to the RIGHT function. Therefore, subtracting 1
from the above formula does the trick. Array enter:
=RIGHT(A1,MATCH("\",MID(A1,LEN(A1)+1-ROW(1:25),1),0)-1). It turns out that the
adding 1 then subtracting 1 do, in fact, cancel each other out, and the more compact
formula is =RIGHT(A1,MATCH("\",MID(A1,LEN(A1)-ROW(1:25),1),0)).
To ensure you will find the last part when the last part may be more than 25 characters,
you should change the ROW(1:25) to be ROW(1:255).
After explaining all that, there is a way to do it without an array formula! By using the
SUSTITUTE function, you can change the last delimiter to some other character, then
search the string for this character, and everything after that character is the last part. The
SUBSTITUTE function has as its syntax, =SUBSTITUTE(text,old text, new text,instance
#). The instance# you want is calculated also by the SUBSTITUTE function: =LEN(A1)-
LEN(SUBSTITUTE(A1,"\","")) returns the number of times "\" occurs (the
SUBSTITUTE is changing \ to null, so the length changes. If the string were “a\a\a”, then
this gives 5-LEN(“aaa”) or 5-3, or 2, the number of backslashes.
Now change the last backslash to some other string, say CHAR(13):
SUBSTITUTE(A1,"\",CHAR(13),LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))).                    This
changes the last backslash to CHAR(13). Now find it: FIND(CHAR(13),
SUBSTITUTE(A1,"\",CHAR(13),LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))                   which
gives the position of this character, and now use it in a MID function to return the last
part: =MID(A1,FIND(CHAR(13), SUBSTITUTE(A1,"\",CHAR(13),LEN(A1)-
Granted, this formula is longer, but it calculates much more quickly than an array

Matching More Than One Column Against A String
In the following illustration we see that there are duplicate names running down column
A. To find an amount (Column C) for a name must depend on some other factor, like a
code (Column B). For example, to find the amount for John with code 3, we can visually
see it is in row 9, and the amount is 158.

But how can we find that using Excel formulas? If columns A and B were combined, for
example, by entering =A2&B2 in cell D2 and filling down, we’d have a unique set of
values to search. That is, in column D we’d see Bob1;Bob2;Bob3, etc. John3 would
appear in cell D9. Then we could use =MATCH(E2&E3,D2:D20,0) and find the row the
result is in. Well, using array formulas, we can simulate the combining of columns A and
B. Cell E4 contains the array-entered formula
=INDEX(C:C,MATCH(E2&F2,$A$1:$A$22&$B$1:$B$22,0)). Since we’re ANDing
A1:A22 with B1:B22, this gives us the array
 MATCHing “John3” to this gives the result we want, 9. Passing this to the INDEX
function gives the number we need, 158.

Are There Duplicate Values In Two Ranges?
There are times when you have two ranges of values and you need to know if there are
any duplicate values within the ranges. Usually, the orientation of the values are the
same, but in this technique we’ll discuss how to make the comparison independent of the
orientation (although you will have to take the orientation into consideration to use the
correct formulas).
In the top half, we see two ranges, A1:A3 and C1:C3, and there’s a 6 in both ranges. As
you can see form cell B6, the TRUE indicates that there is a duplicate. The text box
overlaying cells D4:H5 shows the array-entered formula,
The TRANSPOSE function changes the orientation of A1:A3 to be horizontal, just so it’s
the opposite orientation of the second range. By doing this, Excel will compare each
value in the first array to every value in the second, not simply a one-to-one
correspondence. That is, the 4 in cell C1 will be compared to {1;6;3}, the 5 in C2 will be
compared to {1;6;3}, and the 6 in C3 will be compared to {1;6;3}, giving 9 comparisons
in total. In general, the number of comparisons is given by the number of elements of
each array multiplied together, in this case 3x3. If you dragged across the formula inside
the OR function and pressed the F9 key (calculate), you would see
eighth value is TRUE because that is the comparison of cell C3 against A2.
Since this array of TRUEs and FALSEs are passed to the OR function, any occurrence of
a TRUE will result in a TRUE, indicating there’s a match, or duplicate. If none of the
values match, they will be all FALSE values, which result in a FALSE when ORed
In the bottom half of the illustration, the comparison is already of differing orientations,
so the TRANSPOSE function is not needed, and the range A9:A11 (same values as
before) is being compared to C10:H10. There are 3x6, or 18, comparisons. If you F9 the
formula inside the OR function, you would see, of course,
Notice every sixth FALSE is followed by a semicolon, whereas all the others are
commas. This indicates the orientation.
A Problem, Or Limitation, Of This Technique
There is a problem using this technique. Since one orientation must be row-wise, the
maximum number of values which can be compared is 256. How, then can we find out if
there’s a duplicate if there are more than 256 values? That is, if the ranges to be
compared are A1:A400 vs B1:B400, the TRANSPOSE of either one won’t work. The
array will be “chopped off” after 256 values. Well, there’s another way, using array-
formulas. If you compare two ranges by the formula =MATCH(range1,range2,0) and
array enter it, you will see something like {#N/A;#N/A;2;#N/A;#N/A;4;#N/A}, where
the #N/A’s indicate there’s no match between the particular element of the first array
against all the elements of the second array, and the values indicate there is a match and
in what position the match occurs.
The COUNT function, interestingly, ignores #N/A values and just returns the count of the
number of non-#N/A values, so you can use =COUNT(MATCH(range1,range2,0)).
When this count is 0, there are no matches between the two arrays.

Determining If The Contents Of A Range Are Unique
Suppose you have a worksheet which contains ranges which you want to know if the
items in them are unique. For example, look at the illustration:

Cells A1:A7 are defined as “range”, and the COUNTIF function is used to return an array
of values. Usually, the COUNTIF function takes two arguments: a range, and a criteria,
where the criteria is a simple test. In this case, we’re using the range itself as the criteria,
and therefore the function must be array-entered.
What does COUNTIF(range,range) do for us? Well, each value in the range is used as
the criteria in turn. When the range A1:A7, which evaluates to {1;3;2;4;3;3;4}, is used
twice in the COUNTIF function, the first test is =COUNTIF({1;3;2;4;3;3;4},1) which
counts the number of times the range is equal to 1. This is 1. The second test is
=COUNTIF({1;3;2;4;3;3;4},3) which counts the number of times the range equals 3. The
reason the criteria is 3 is that this is the second value in the range. There are three 3’s.
Similarly for the other 5 tests: there is one 2, two 4’s, three 3’s, three 3’s, and two 4’s.
Therefore, =COUNTIF({1;3;2;4;3;3;4},{1;3;2;4;3;3;4}) produces the array
Passing this to the MAX function, =MAX(COUNTIF(range,range)), returns the largest
value of the array, or 3. Since this doesn’t equal 1, the result is FALSE, which indicates
the range is not made up of unique values. The range C8:C14 in the illustration contains
the characters a-g. The COUNTIF(Range2,Range2) returns the array {1;1;1;1;1;1;1}
because each of the items in the criteria returns a 1: =COUNTIF(Range2,“a”) counts the
number of times the Range2 equals “a”, which is 1, and similarly for “b”, “c”, etc.
MAX({1;1;1;1;1;1;1}) is 1, which, when compared to a 1, returns TRUE, indicating the
range contains unique values.
There’s another very powerful formula which counts the number of unique values in a
range: =SUM(1/COUNTIF(range,range)), array-entered. Suppose the range consisted of
the 7 values {11,12,13,11,14,11,12}. This function would return 4 because there are 4
unique values. The COUNTIF part returns the array {3,2,1,3,1,3,2} where each value is
the number of times the corresponding values occur. That is, 11 occurs 3 times, 12 twice,
13 once, etc. Dividing this array into 1 gives the array {.33333,.5,1,.33333,1,.33333,.5}.
Each of the .33333’s (or 1/3) corresponds to the 3’s, and there are 3 of them. The .5’s
correspond to the 2’s, and there are 2 of them, etc. Adding them up “brings together” the
3-thirds, 2-halves, etc, and therefore counts how many there are! That is, we have 3 x
.33333, 2 x .5, and 2 1’s. This totals 4, the number of unique values. So you could use
this formula as well as the MAX function just discussed.

Calculating The Sum Of The Digits
Suppose cell A1 contains the value 15234. The digits add up to 15. If you can make each
digit in cell A1 occupy its own cell, then you can just SUM the results. This can be
simulated by using an array formula. The array formula which works is
=SUM(1*MID(A1,ROW(INDIRECT("1:"&LEN(A1))),1)). Let’s first understand this
formula by looking at the formula we’d use if we knew the length of cell A1 were 5:
=SUM(1*MID(A1,ROW(1:5),1)). This expands to =SUM(1*MID(A1,{1;2;3;4;5},1))
which becomes =SUM(1*{"1";"5";"2";"3";"4"}) which becomes =SUM({1;5;2;3;4})
which is 15.
But, Excel won’t allow us to enter ROW(1:LEN(A1)). We can create this by using the
INDIRECT function, INDIRECT("1:"&LEN(A1)). This becomes INDIRECT(“1:5”)
which Excel “understands”, and passing this to the ROW function gives us the array we
need, {1;2;3;4;5}. Another attempt might be to just use an array which is large enough to
cover any number entered. So we could try =SUM(1*MID(A1,ROW(1:30),1)), but this
gives a #VALUE! error because once Excel evaluates MID(A1,6,1) this becomes null,
(“”), and when this is multiplied by 1 it becomes an error. SUMming arrays with errors
results in an error.
Extracting Just The Numeric Portion Of A Cell
If you have a column of cells which contain alphanumeric data, such as a part number,
you may want to be able to sort by the numeric portion. But extracting the numeric
portion may not be easy if the alpha size varies. For example, if one part number is
ABC123 and another is PART03772, finding the 123 and the 3772 is not a trivial task.
Here we’ll explore one method to do it. The first part is to determine how to find the
location of the first digit. For this illustration, let’s assume cell A1 contains ABC123.
You can change the string into an array by an array-formula such as
The function ROW(1:10) is used for the array portion, the 10 being an arbitrarily large
enough number to “parse” each string (assuming no part will have an alpha section longer
than 10 characters). This formula would give the array
{“A”,“B”,“C”,“1”,“2”,“3”,“”,“”,“”,“”}. We still can’t distinguish a real difference
between letters and numbers here, but if we were to multiply this array by 1:
=1*MID(A1,ROW(1:10),1) we get the array {#VALUE!, #VALUE!, #VALUE!,1,2,3,
Notice there are values 1, 2, and 3 embedded in the resulting array. Here we can see a
difference! What about now passing this array to the ISERROR function?
=ISERROR(1*MID(A1,ROW(1:10),1)) gives the array
{TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,TRUE...} and here we can find the first
FALSE condition (the position which corresponds to the first digit in the part number) by
using MATCH: =MATCH(FALSE,ISERROR(1*MID(A1,ROW(1:10),1)),0) which returns a
4.Now we need to extract that part of the part number using MID:
=MID(A1,MATCH(FALSE,ISERROR(1*MID(A1,ROW(1:10),1)),0),255). But that returns
the numeric portion as text which won’t sort the way we want (2 will sort after 123
because as text “2” is after “1”), so to convert it back to a number we need to multiply it
by 1: =1*MID(A1,MATCH(FALSE,ISERROR(1*MID(A1,ROW(1:10),1)),0),255)
Array-enter this, fill down and sort by the result.

Finding The Closest Value To The Average
When you use the AVERAGE function, the result will not necessarily be one of the
values in the range. There may be times when you want to know which value is the
closest. For example, in the illustration, you can see that cell B8 returns the value 23
which is the closest value to the average of 21.8, shown in cell B7.
When you need to find a close value, you’re not interested in whether the value is on the
high side or low side. That is, for the average of 21.8, 22 is closer than 21 -- subtracting
the average from these values produces a .2 and a negative .8. Since you’re not interested
in positive or negative, you can’t just take the minimum value, but you can take the
minimum value of the absolute differences.
To get the absolute differences, you take each value and subtract the average, then pass
this calculation to the ABS function. So far, then you have =ABS(Units-
AVERAGE(Units)). This part produces the array {11.8;6.8;1.2;23.2;5.8}: (10 - 21.8 is -
11.8, 15 - 21.8 is -6.8, etc. The negative sign disappears because of the ABS function).
Now we have a range of differences, but we’re interested in the smallest of these, so this
is passed to the MIN function. This returns 1.2. Now we have to find where the 1.2 is in
the range, so we MATCH this MIN(ABS(Units-AVERAGE(Units))) against the range
ABS(Units-AVERAGE(Units)), and the third parameter of the MATCH function, zero,
requests an exact match, so we find the 1.2 in the 3rd item of the array. Pass this “3” to
the INDEX function, and Excel returns the closest value.
The final formula is =INDEX(units,MATCH(MIN(ABS(units-
AVERAGE(units))),ABS(units-AVERAGE(units)),0)) array-entered, of course.

Adding Conditions Meeting At Least One Criteria
Suppose you have a worksheet which lists names, dates, and amounts, and you wish to
add up all the amounts for which the name is Bob OR the date is before 5/1/98.
If you try some variety of using an OR-function you will meet with failure because if any
of the items returns TRUE, then the entire OR-function will return TRUE, and you will
probably add up all the amounts. For example, if you try
=SUM(IF(OR(Name=“Bob”,Month(Date)<5),Amount)) you’ll get a number which is
probably wrong because Name=“Bob” might evaluate to
when these arrays are ORed together, the result is simply TRUE, not an array consisting
of TRUE/FALSE. Therefore, the formula reduces to =SUM(IF(TRUE,Amount)) which,
or course, is the sum of all the amounts.
The formula for the solution is the array-entered:
Let’s see how this works. Also, let’s assume the values for Amount are
{1;2;3;4;5;6;7;8}. If you ADD the two TRUE/FALSE arrays detailed above, you get the
array {1;1;0;2;1;2;0;1}. Note: TRUE + TRUE evaluates to 2, TRUE + FALSE evaluates
to 1 and FALSE + FALSE evaluates to 0. What is this? Well, each 1 corresponds to a
TRUE+FALSE or FALSE+TRUE, meaning one of the conditions was met (Name was
“Bob” or Month(Date) was less than 5). 2 means both conditions were met, and zero
means neither condition was met. You’re interested in the non-zeros. Therefore,
comparing this array to zero: {1;1;0;2;1;2;0;1}>0 evaluates to
{TRUE;TRUE;FALSE;TRUE;TRUE;TRUE;FALSE;TRUE},and when this is multiplied
by Amount, it evaluates to {1;2;0;4;5;6;0;8}. When this is SUMmed together you get 26.
If you had wanted to add the amounts together when both conditions are met, you could
use the array-entered formula: =SUM((Name="Bob")*(MONTH(Date)<5)*Amount).

Creating a calendar with a single array-entered formula
People seem to always want t be able to create a calendar in Excel, for some reason, so
here’s a way to do so using one formula. It’s a little tricky, but with the techniques used
so far, it’ll be straightforward. It’s best to define 2 names, week and weekday. Week is
defined as an array constant, ={0;1;2;3;4;5} and weekday as ={1,2,3,4,5,6,7}. Notice that
week has semicolons separating the entries, implying that it’s a column-oriented array,
and weekday contains commas, implying a row-oriented array.
Three cells are used to drive the calendar in the session: A1, which contains =TODAY(),
B1, which contains =WEEKDAY(B2), and B2 which contains
=DATE(YEAR(A1),MONTH(A1),1). Cell B2, then, is the first of the month of the date
entered in cell A1. If, by default, A1 contains =TODAY(), then the calendar will open up
displaying the current month. If you wanted any other month, you can simply enter a new
date in cell A1. Cell B1 is the day of the week of cell B2, as a number, where 1=Sunday.
A 6 row x 7 column selection is made and the formula =Calendar is array-entered.
Calendar is =week*7+weekday+B2-B1. Let’s examine how this all works. Let’s assume
we’re working with February, ’98. The part of the formula =week*7+weekday will
always be the same, namely the numbers 1-42. How? Week*7 is the column-oriented
array {0;7;14;21;28;35}. When this is added to the row-oriented array {1,2,3,4,5,6,7},
Excel expands to give
,33,34,35;36,37,38,39,40,41,42}. Notice the semi-colons after the 7, 14, etc. This
indicates the next row is begins there.
To this array is added B2, which contains the date for the first day of the month. For
February ’98, this is the serial # 35827. Now we have an array consisting of
{35828,35829, …, etc.}. Now the weekday of 2/1/98 is subtracted. Since 2/1 is a Sunday,
the weekday is 1, and the array becomes {35827,35828, …, etc.).
Since these are valid serial #s, you can simply format them as “d”, and you’ll see the day
of the month. Since 2/1/98 is a Sunday, the calendar starts right in with the 1 in the upper
left cell of the 6x7 range. By making the row heights high and formatting the cell’s
alignment to be vertical:top, horizontal:right, it looks like a “real” calendar!
A few notes, however. If we looked at November ’97, for example, we would see the
upper left cell start with a 26. This is because the entire 6x7 array is filled with serial
numbers and the Sunday in the upper left corner is the 26th of October ’97. The whole
first row contains {26,27,28,29,30,31,1} and we only want to see the 1. Similarly, the
bottom row contains {30,1,2,3,4,5,6} because it extends into December ’97 and here we
only want to see the 30.
This was fixed by making the formula a bit more complicated, but makes the result just
what we want:
This formula is array-entered, of course, and says that if the day of the month is >15, then
in the first row show blank. Let’s examine this a bit more before looking at the rest of the
formula. In the first row, we saw some days from the previous month (when we looked at
11/97). This was row 5 in the session. So, if the day is over 15 (15 is fairly arbitrary – the
first number we could see from the previous month is 26, so 25 would have worked as
well), and the row is the first row, don’t show it: =IF(DAY(Calendar)>15,IF(ROW()=5,
Similarly, in the last row(s), we don’t want to show the days from the beginning of the
next month, so here we’re looking at IF(DAY(Calendar)<15,IF(ROW()>8,
"",Calendar… which effectively removes the beginning of the next month. We chose
ROW()>8 rather than ROW()=10 because some months are short , like 2/98, and only
take up 4 rows. In that case we want to blank out rows 5 and 6.

Shared By: