{"id":63843,"date":"2007-10-09T22:22:00","date_gmt":"2007-10-09T22:22:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/10\/09\/hey-scripting-guy-how-can-i-insert-blank-rows-and-formulas-into-an-office-excel-worksheet\/"},"modified":"2007-10-09T22:22:00","modified_gmt":"2007-10-09T22:22:00","slug":"hey-scripting-guy-how-can-i-insert-blank-rows-and-formulas-into-an-office-excel-worksheet","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-insert-blank-rows-and-formulas-into-an-office-excel-worksheet\/","title":{"rendered":"Hey, Scripting Guy! How Can I Insert Blank Rows (and Formulas) Into an Office Excel Worksheet?"},"content":{"rendered":"<p><H2><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"> <\/H2>\n<P>Hey, Scripting Guy! I have some extremely large Office Excel worksheets, and I need to insert a blank row every 240 lines; in that new row I then need to insert a formula that calculates the average of the preceding 240 rows. As you might expect, this is extremely tedious, and I have a <I>lot<\/I> of these worksheets. How can I write a script that inserts rows and formulas for me?<BR><BR>&#8212; BS<\/P><IMG border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" border=\"0\" alt=\"Script Center\" align=\"right\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" height=\"288\"><\/A> \n<P>Hey, BS. You know, we\u2019re sure that a lot of people wonder what the Scripting Guys do in their spare time. Well, we can\u2019t speak for the other Scripting Guys, but we <I>can<\/I> tell you that the Scripting Guy who writes this column has an asbolutely fascinating hobby: for reasons even <I>he<\/I> doesn\u2019t fully understand, he spends most of his spare time visiting obscure, out-of-the-way airports that nobody else ever goes to.<\/P>\n<P>For example, earlier this year, the Scripting Guy who writes this column was excited about the chance to visit the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/jul07\/hey0713.mspx\"><B>airport in Walla Walla, WA<\/B><\/A>. As it turned out, however, he never got that chance: after driving the 45 miles from the Tri-Cities to Walla Walla, he discovered that \u2013 thanks to modern air travel, which primarily involves airplanes that don\u2019t actually <I>do<\/I> any traveling \u2013 the flight he was supposed to meet had been cancelled. Instead, he ended up driving <I>back<\/I> to the Tri-Cities, hung around the Tri-Cities airport for awhile (after the rescheduled flight was delayed, then delayed again), and then drove back to Walla Walla.<\/P>\n<P>And all just to watch the Scripting Son play baseball.<\/P>\n<P>And then, just last Friday, this same Scripting Guy (and that same Scripting Son) got to visit the <A href=\"http:\/\/www.pullman-wa.gov\/airport\/\" target=\"_blank\"><B>Pullman-Moscow Regional Airport<\/B><\/A> in Pullman, WA. (All part of the fun and excitement of <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/oct07\/hey1005.mspx\"><B>Vandal Preview Day<\/B><\/A>.) Is the Pullman-Moscow Regional Airport a small airport? You might say that: after all, the entire terminal is housed in a single room, a room that includes a rental car counter, a ticket desk, and the baggage claim. The Scripting Guy who writes this column and his son arrived about 10:45 PM for a flight scheduled to land at 11:10 PM. For the next 20 minutes or so, they were the only people in the entire airport; there was not a soul to be seen anywhere. Including anyone who, we assume, was supposed to be <I>working<\/I> at the airport.<\/P>\n<P>So was that kind of spooky? Not really; there were plenty of things to do at the airport. For example, there were several decks of cards lying around, so the Scripting Son and his father played a spirited game of War. (A game won by the Scripting Dad, of course.) In addition there was a self-service bookstore in the terminal, a \u201cbookstore\u201d that was really just a couple bookcases filled with books along with a slot for depositing your money. The Scripting Guy who writes this column actually bought four books (nice ones) for $20. Now that <I>was<\/I> cool: try buying even <I>one<\/I> book for $20 at your typical big city airport.<\/P>\n<P>At any rate, between the self-service bookstore, the decks of cards, and the two vending machines (not to mention the free parking), the Pullman-Moscow Airport had pretty much anything a traveler (or someone assigned to pick up a traveler) could ever need. Well, except maybe for one thing: it didn\u2019t have a script that could periodically insert blank rows (and formulas) into an Excel spreadsheet. But that\u2019s OK; after all, the Scripting Guy who writes this column would never leave home without a script like that:<\/P><PRE class=\"codeSample\">Const xlShiftDown = -4121<\/p>\n<p>Set objExcel = CreateObject(&#8220;Excel.Application&#8221;)\nobjExcel.Visible = True<\/p>\n<p>Set objWorkbook = objExcel.Workbooks.Open(&#8220;C:\\Scripts\\Test.xls&#8221;)\nSet objWorksheet = objWorkbook.Worksheets(1)<\/p>\n<p>i = 1\nj = 1<\/p>\n<p>Do Until objWorkSheet.Cells (i, 1) = &#8220;&#8221;\n    If j = 241 Then\n        Set objRange = objWorksheet.Cells(i, 1).EntireRow\n        objRange.Insert(xlShiftDown)<\/p>\n<p>        strFormula = &#8220;=AVERAGE(A&#8221; &amp; i &#8211; 1 &amp; &#8220;:A&#8221; &amp; i &#8211; 240 &amp; &#8220;)&#8221;\n        objWorksheet.Cells(i, 1) = strFormula\n        objWorksheet.Cells(i, 1).Interior.ColorIndex = 44<\/p>\n<p>        j = 0\n    End If\n    j = j + 1\n    i = i + 1\nLoop<\/p>\n<p>If j &lt;&gt; 0 Then\n    Set objRange = objWorksheet.Cells(i, 1).EntireRow\n    objRange.Insert(xlShiftDown)<\/p>\n<p>    strFormula = &#8220;=AVERAGE(A&#8221; &amp; i &#8211; 1 &amp; &#8220;:A&#8221; &amp; i &#8211; j + 1 &amp; &#8220;)&#8221;\n    objWorksheet.Cells(i, 1) = strFormula\n    objWorksheet.Cells(i, 1).Interior.ColorIndex = 44\nEnd If\n<\/PRE>\n<P>So how does this script work? We were afraid you were going to ask that question; this is definitely a complicated-looking batch of code, isn\u2019t it? But let\u2019s see if we can sit down and figure this out together.<\/P>\n<P>As you can see, we start out by defining a constant named xlShiftDown and setting the value to -4121; we\u2019ll use this constant to tell Excel which way to shift the existing cells each time we insert a new row. <\/P>\n<TABLE id=\"ERE\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Scripting GuysTrivia<\/B>. By amazing coincidence, -4121 is both the Scripting Editor\u2019s batting average for the past softball season <I>and<\/I> her score on the SAT test. What do you suppose the odds are of <I>that<\/I>?<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>After we define the constant, we create an instance of the <B>Excel.Application<\/B> object and then set the <B>Visible<\/B> property to True; that gives us a running instance of Excel that we can see on screen. We then use the following two lines of code to open the file C:\\Scripts\\Test.xls and bind us to the first worksheet in that file:<\/P><PRE class=\"codeSample\">Set objWorkbook = objExcel.Workbooks.Open(&#8220;C:\\Scripts\\Test.xls&#8221;)\nSet objWorksheet = objWorkbook.Worksheets(1)\n<\/PRE>\n<P>From there we then assign the value 1 to a pair of counter variables, i and j. We\u2019re going to use i to keep track of our current location in the worksheet, and we\u2019re going to use j to let us know when it\u2019s time to insert a row. With any luck, exactly <I>how<\/I> we\u2019re going to accomplish both of those feats will become clear in a minute or two.<\/P>\n<P>For educational purposes, we\u2019re assuming that we have a very simple spreadsheet, one with a bunch of numbers in column A, and with no blank rows between those numbers. With that in mind, our next step is to set up a Do Until loop that runs until we encounter a blank cell in column A; when that happens, we\u2019re going to assume that we\u2019ve reached the end of the worksheet. And, just like we said, we\u2019re using the counter variable i to keep track of our location in the worksheet:<\/P><PRE class=\"codeSample\">Do Until objWorkSheet.Cells (i, 1) = &#8220;&#8221;\n<\/PRE>\n<P>Because i is equal to 1, that means that, the first time through the loop, we\u2019ll be looking at the value of cell row 1, column 1. That brings us to this line of code:<\/P><PRE class=\"codeSample\">If j = 241 Then\n<\/PRE>\n<P>What\u2019s this for? Well, BS wants to insert a new row every 240 rows. We use the counter variable j to keep track of the rows as we work our way down the spreadsheet. If j is not equal to 241, that means that we haven\u2019t counted off 240 rows yet. Therefore, we simply skip the If-Then block, increment the values of both counter variables by 1, then repeat this process with the next row in the worksheet.<\/P>\n<P>Ah, but suppose that counter variable j <I>is<\/I> equal to 241. If that\u2019s the case, that means that we just passed row number 240; in turn, that means it\u2019s time to enter a blank row:<\/P><PRE class=\"codeSample\">Set objRange = objWorksheet.Cells(i, 1).EntireRow\nobjRange.Insert(xlShiftDown)\n<\/PRE>\n<P>What are we doing here? Well, for starters, we\u2019re creating an instance of Excel\u2019s <B>Range<\/B> object, a Range object that encompasses the current row. (How do we know that this Range object encompasses the current row? Well, <B>objWorksheet.Cells(i, 1)<\/B> gives us the current cell in column A, while the <B>EntireRow<\/B> property gives us all the other cells in the row.) We then call the <B>Insert<\/B> method to insert a new row, using the constant xlShiftDown to tell the script to insert the new row by moving existing cells down a row.<\/P>\n<P>Now, if all we wanted to do was periodically insert blank rows into our spreadsheet then we\u2019d be done; in fact, if all you <I>do<\/I> want to do is periodically insert blank rows into your spreadsheet here\u2019s a script that does just that:<\/P><PRE class=\"codeSample\">Const xlShiftDown = -4121<\/p>\n<p>Set objExcel = CreateObject(&#8220;Excel.Application&#8221;)\nobjExcel.Visible = True<\/p>\n<p>Set objWorkbook = objExcel.Workbooks.Open(&#8220;C:\\Scripts\\Test.xls&#8221;)\nSet objWorksheet = objWorkbook.Worksheets(1)<\/p>\n<p>i = 1\nj = 1<\/p>\n<p>Do Until objWorkSheet.Cells (i, 1) = &#8220;&#8221;\n    If j = 241 Then\n        Set objRange = objWorksheet.Cells(i, 1).EntireRow\n        objRange.Insert(xlShiftDown)\n        j = 0\n    End If\n    j = j + 1\n    i = i + 1\nLoop\n<\/PRE>\n<P>Of course, we don\u2019t want to just insert blank rows in our worksheet; we want to stick a formula for calculating averages into those blank rows. And here\u2019s how we do <I>that<\/I>:<\/P><PRE class=\"codeSample\">strFormula = &#8220;=AVERAGE(A&#8221; &amp; i &#8211; 1 &amp; &#8220;:A&#8221; &amp; i &#8211; 240 &amp; &#8220;)&#8221;\nobjWorksheet.Cells(i, 1) = strFormula\n<\/PRE>\n<P>We thought you might have a question about that first line of code. When you insert a formula into a cell, you need to use syntax similar to this:<\/P><PRE class=\"codeSample\">=AVERAGE(A240:A1)\n<\/PRE>\n<P>Believe it or not, our first line of code constructs that very formula. To do so we combine these elements:<\/P>\n<TABLE border=\"0\" cellSpacing=\"0\" cellPadding=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>The string value <B>=AVERAGE(A<\/B>.<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>The current row minus 1 (<B>i \u2013 1<\/B>). Why i minus 1? Well, currently we\u2019re on row 241 and we only want our formula to average the rows from 1 to 240. Thus we need to subtract 1 from the current row number. If we don\u2019t, we\u2019ll get a whole host of circular reference errors. <BR><BR>Um, not that the Scripting Guy who writes this column got a whole host of circular reference errors on his first try at writing this script, mind you.<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>The string value <B>:A<\/B><\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>The starting row for our set of 240 rows. How do we calculate that? By subtracting 240 from the counter variable i. If we subtract 240 from 241 we get 1, which is good; after all, the first row in our dataset is row 1.<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>The string value <B>)<\/B>.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>Add them all together and you get this:<\/P><PRE class=\"codeSample\">=AVERAGE(A240:A1)\n<\/PRE>\n<P>And yes, that <I>is<\/I> a little backwards; you\u2019d expect the formula to start with A1 and end with A240:<\/P><PRE class=\"codeSample\">=AVERAGE(A1:A240)\n<\/PRE>\n<P>But that\u2019s all right. We thought this \u201cbackwards\u201d method was a little easier to follow, and Excel doesn\u2019t care: go ahead and enter the formula like this and Excel will automatically correct it for you.<\/P>\n<P>Good old Excel.<\/P>\n<P>After writing the formula to the current cell, we next reset the value of j to 0. Why? Because it\u2019s now time to start counting off the next set of 240 rows. To <I>that<\/I> end, we increment both our counter variables by 1, then loop around and try this with the next row in the worksheet:<\/P><PRE class=\"codeSample\">j = j + 1\ni = i + 1\n<\/PRE>\n<P>Incidentally, you can easily modify this script to insert blank rows at an interval other than 240. For example, suppose you want to insert a blank row every 25 rows. That\u2019s fine. To do that, first change the If Then statement to check to see if j is equal to <B>26<\/B> (one more than the desired interval):<\/P><PRE class=\"codeSample\">If j = 26 Then\n<\/PRE>\n<P>And then make sure you subtract the interval value (<B>25<\/B>) when putting together the formula:<\/P><PRE class=\"codeSample\">strFormula = &#8220;=AVERAGE(A&#8221; &amp; i &#8211; 1 &amp; &#8220;:A&#8221; &amp; i &#8211; 25 &amp; &#8220;)&#8221;\n<\/PRE>\n<P>Pretty easy, huh?<\/P>\n<P>Oh, good point; what <I>is<\/I> this line of code for:<\/P><PRE class=\"codeSample\">objWorksheet.Cells(i, 1).Interior.ColorIndex = 44\n<\/PRE>\n<P>This is optional, but to make it a bit easier to distinguish formula cells from the other cells in column A we use this line of code to change the background color of the formula cells to orange. (Give it a try and you\u2019ll see what we mean.)<\/P>\n<P>After we exit the loop we then check to see whether or not j is equal to 0; if it is, then we\u2019re done; we\u2019ve averaged all the rows in the last series. If j is <I>not<\/I> equal to 0 (for example, if j is equal to 113) then we have a few rows (in this case, 113) that haven\u2019t been averaged. We use this block of code to take care of that little problem:<\/P><PRE class=\"codeSample\">Set objRange = objWorksheet.Cells(i, 1).EntireRow\nobjRange.Insert(xlShiftDown)<\/p>\n<p>strFormula = &#8220;=AVERAGE(A&#8221; &amp; i &#8211; 1 &amp; &#8220;:A&#8221; &amp; i &#8211; j + 1 &amp; &#8220;)&#8221;\nobjWorksheet.Cells(i, 1) = strFormula\nobjWorksheet.Cells(i, 1).Interior.ColorIndex = 44\n<\/PRE>\n<P>And that \u2013 at long last \u2013 is that.<\/P>\n<P>What\u2019s that? You have one last question? Now that he\u2019s taken care of the insert-a-blank-row-and-formula-into-a-spreadsheet problem, you want to know if the Scripting Guy who writes this column has been left with a whole bunch of time on his hands? In turn, does that mean he\u2019ll soon be traveling to new locations and new airports, locations and airports even <I>more<\/I> exotic than Walla Walla, WA or Moscow, ID? Let\u2019s put it this way: we sure hope not.<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I have some extremely large Office Excel worksheets, and I need to insert a blank row every 240 lines; in that new row I then need to insert a formula that calculates the average of the preceding 240 rows. As you might expect, this is extremely tedious, and I have a lot [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[710,48,49,3,5],"class_list":["post-63843","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-excel-spreadsheet","tag-microsoft-excel","tag-office","tag-scripting-guy","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I have some extremely large Office Excel worksheets, and I need to insert a blank row every 240 lines; in that new row I then need to insert a formula that calculates the average of the preceding 240 rows. As you might expect, this is extremely tedious, and I have a lot [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/63843","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=63843"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/63843\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=63843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=63843"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=63843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}