{"id":54623,"date":"2009-01-13T11:55:00","date_gmt":"2009-01-13T11:55:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/01\/13\/hey-scripting-guy-how-do-i-run-an-office-excel-macro-on-multiple-workbooks\/"},"modified":"2009-01-13T11:55:00","modified_gmt":"2009-01-13T11:55:00","slug":"hey-scripting-guy-how-do-i-run-an-office-excel-macro-on-multiple-workbooks","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-do-i-run-an-office-excel-macro-on-multiple-workbooks\/","title":{"rendered":"Hey, Scripting Guy! How Do I Run an Office Excel Macro on Multiple Workbooks?"},"content":{"rendered":"<h2><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> <\/h2>\n<p>Hey, Scripting Guy! I don&#8217;t know about you, but I love Microsoft Office Excel macros. Come <a href=\"http:\/\/en.wikipedia.org\/wiki\/Valentines_day\" target=\"_blank\">Valentine&#8217;s Day<\/a>, my computer gets a card. Office Excel macros save me so much time, it is just unbelievable. There is just one problem, and that is that I have to open Office Excel and manually run the macro. While this is not normally a problem, it just became one. My pointy-headed boss (PHB) just decided that he wants a new cover sheet for the <a href=\"http:\/\/en.wikipedia.org\/wiki\/TPS_report_%28Office_Space%29\" target=\"_blank\">TPS report<\/a>\u2014not literally, but figuratively. Let me explain: There is a folder with hundreds of Office Excel workbooks in it, and he wants this macro to be run on all of them. The macro itself is a company macro and it automatically exists in all workbooks. The PHB wants me to open up all the workbooks, click the <b>Macro<\/b> button, and run this stupid macro. It will take me hours and hours to do it. I told him we should hire a temporary worker to do it, and he said, and I quote, &#8220;No rush. You can do it in your spare time. As long as it is done before the end of the quarter, we will be fine.&#8221; The end of the quarter is next week, and I <i>have<\/i> no spare time! Can you please help me?<\/p>\n<p>&#8211; GG<\/p>\n<p><img decoding=\"async\" height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"><\/p>\n<p>Hi GG,<\/p>\n<p>As much as I would like to help, I am not going to come over and help you open a bunch of workbooks, click a macro button, and run the macro. I think I would die of boredom in less than 15 minutes. You see, one reason I became a scripting guy is because I have a low tolerance for banality, and I despise time-wasting, mind-numbing activities. So rather than coming over and helping you click buttons, would it be okay if I write you a script? <\/p>\n<p>Believe it or not, we can access Office Excel macros from a script. We already know that we can use Windows PowerShell to find particular types of files, so all we need to do is write a script that will search your folder for Office Excel workbooks, and then we can use the Office Excel automation model to open the workbooks and run the macro. Pretty cool huh? <\/p>\n<table class=\"dataTable\" id=\"EGD\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p class=\"lastInCell\">The Office Excel automation model is <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb255823.aspx\">documented here on MSDN<\/a>. Here are previous <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/office.mspx\">&#8220;Hey, Scripting Guy!&#8221; articles<\/a> that illustrate using VBScript to automate Microsoft Excel. The <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/officetips\/archive.mspx\">Office space archive<\/a> also has numerous examples of using VBScript with Office Excel. You can also find lots of examples of automating Office Excel in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/default.mspx?mfr=true\">Script Center Repository<\/a>. Perhaps I also saved the best for last. The Community-Submitted Scripts Center has a <i>ton<\/i> of scripts that automate Office Excel. Here is the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/csc\/scripts\/office\/excel\/index.mspx\">direct link to that gold mine of information<\/a>. Look in the Microsoft Office section. If you are new to using Microsoft PowerShell, you can get a jump-start on it with the resources in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/msh\/default.mspx?mfr=true\">Windows PowerShell hub<\/a>.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>Here is today\u2019s&nbsp;script:<\/p>\n<pre class=\"codeSample\">$excel = new-object -comobject excel.application\n$excelFiles = Get-ChildItem -Path C:\\fso -Include *.xls, *.xlsm -Recurse\nForeach($file in $excelFiles)\n{\n $workbook = $excel.workbooks.open($file.fullname)\n $worksheet = $workbook.worksheets.item(1)\n $excel.Run(\"CreateChart\")\n $workbook.save()\n $workbook.close()\n}\n$excel.quit()\n<\/pre>\n<p>The script begins by creating an instance of the <b>Excel.Application<\/b> object. This is the main object that you use when you are working with automating Office Excel. From the <b>Excel.Application<\/b> object, we gain access to all the other items that are needed for automation. To create an object in Windows PowerShell, we use the <b>New-Object<\/b> cmdlet. This cmdlet has an option of creating a COM object, and this is what we need here. This is the same object you would use if you were working in VBScript. Because we will need to use the <b>Excel.Application<\/b> object later in our script, we store the object in a variable we call <b>$excel<\/b>. This is seen here:<\/p>\n<pre class=\"codeSample\">$excel = new-object -comobject excel.application<\/pre>\n<p>Next we need to obtain a list of all the .xls and .xlsm files in the folder, and to do this we use the <b>Get-ChildItem<\/b> cmdlet. If you are not familiar with it, a file with an .xlsm extension is a macro-enabled Office Excel workbook. This file type was introduced in Microsoft Office 2007. To limit our search to only these two types of files, we use the <b>include<\/b> switch with the <b>Get_ChildItem<\/b> cmdlet. The <b>include<\/b> switch is allowed to receive an array of file types, and we can therefore use more than one file type separated by commas. The <b>recurse<\/b> parameter is used to tell <b>Get-ChildItem<\/b> to burrow its way down through the folder. The resulting collection of file objects is stored in the <b>$excelFiles<\/b> variable. This line of code is shown here: <\/p>\n<pre class=\"codeSample\">$excelFiles = Get-ChildItem -Path C:\\fso -Include *.xls, *.xlsm \u2013Recurse<\/pre>\n<p>We then need to work our way through the collection of files stored in the <b>$excelFiles<\/b> variable. Whenever you hear the word <b>collection<\/b> you should think <b>foreach<\/b>, or in VBScript you should think <b>foreach next<\/b>. The variable <b>$file<\/b> is used to allow us to access a single file at a time from the collection. This line of code is seen here: <\/p>\n<pre class=\"codeSample\">Foreach($file in $excelFiles)<\/pre>\n<p>Now we need to open the Office Excel workbook. To do this, we use the <b>open<\/b> method from the workbooks collection. We get the <b>workbooks<\/b> collection by using the <b>workbooks<\/b> property from the <b>Excel.Application<\/b> object. When we use the <b>open<\/b> method, we need to supply the path to the workbook we wish to open. The <b>open<\/b> method returns a <b>workbook<\/b> object, which we store in the variable <b>$workbook<\/b> as seen here: <\/p>\n<pre class=\"codeSample\">$workbook = $excel.workbooks.open($file.fullname)<\/pre>\n<p>We then use the <b>worksheets<\/b> property from the <b>workbook<\/b> object to obtain a collection of worksheets. We then use the <b>item<\/b> method to return the first worksheet in the collection. We store that worksheet in the variable <b>$worksheet<\/b>. This is seen here:<\/p>\n<pre class=\"codeSample\">$worksheet = $workbook.worksheets.item(1)<\/pre>\n<p>After we have selected a specific worksheet, we use the <b>run<\/b> method from the <b>Excel.Application<\/b> object to run a specific macro. The macro is seen here:<\/p>\n<p><img decoding=\"async\" height=\"380\" alt=\"Image of the macro being run\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/january\/hey0113\/hsg_excel2_01.jpg\" width=\"500\" border=\"0\"><\/p>\n<p>&nbsp;<\/p>\n<p>The <b>run<\/b> method can be used to run either a macro or a function. This line of code is seen here:<\/p>\n<pre class=\"codeSample\">$excel.Run(\"CreateChart\")<\/pre>\n<p>When you run the script, you will not see any output on the screen. But if you open your Office Excel workbook, you will see that the macro ran and created a nice chart. This is seen here:<\/p>\n<p><img decoding=\"async\" height=\"380\" alt=\"Image of the results of the macro having been run\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/january\/hey0113\/hsg_excel2_02.jpg\" width=\"500\" border=\"0\"><\/p>\n<p>&nbsp;<\/p>\n<p>Now that we have run the macro, we want to save the workbook and then close it out: <\/p>\n<pre class=\"codeSample\">$workbook.save()\n$workbook.close()\n<\/pre>\n<p>We continue looping through the collection of workbooks until we are done. When we are done, we call the <b>quit<\/b> method to end the Office Excel process: <\/p>\n<pre class=\"codeSample\">$excel.quit()<\/pre>\n<p>Well, GG, that is about it. I sincerely hope this script will ease your workload and help ease some of the tension you have at work. Sorry I do not have a script to transform a pointy-headed boss into a normal human being. See you tomorrow. Until then, peace!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I don&#8217;t know about you, but I love Microsoft Office Excel macros. Come Valentine&#8217;s Day, my computer gets a card. Office Excel macros save me so much time, it is just unbelievable. There is just one problem, and that is that I have to open Office Excel and manually run the macro. [&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":[48,49,3,45],"class_list":["post-54623","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-microsoft-excel","tag-office","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I don&#8217;t know about you, but I love Microsoft Office Excel macros. Come Valentine&#8217;s Day, my computer gets a card. Office Excel macros save me so much time, it is just unbelievable. There is just one problem, and that is that I have to open Office Excel and manually run the macro. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54623","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=54623"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54623\/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=54623"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54623"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54623"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}