C, PHP, VB, .NET

Дневникът на Филип Петров


* Записване на макроси – пример с Excel

Публикувано на 27 септември 2015 в раздел Макроси VBA.

Както вече споменахме, почти всяко наше действие в софтуерния продукт би могло да бъде програмирано във VBA. Това включва писане на текст, натискане на бутон от лентата с интструментите, форматиране, и др. Записването на макроси е начин да генерираме автоматично код във VBA, вместо да го пишем на ръка. С натискането на специален бутон ние караме VBA да започне да следи какво правим в софтуерния продукт. След като извършим желаната последователност от действия и натиснем бутон стоп, ние можем да ги запазим и впоследствие да преизползваме.

Нека например имаме документ в Excel, в който ще запазим множество таблици с имена, факултетни номера и оценки на студенти - всяка таблица ще отговаря на различна учебна група. В допълнителна клетка ще изчисляваме техния среден успех. Искаме да направим макрос, чрез който при добавяне на нова таблица да можем да извършим автоматично стандартното форматиране - добавянето на заглавния ред и формулата за среден успех. Ще започнем от празна таблица с нашата първа учебна група. Първото, което трябва да направим, е да стартираме записването на макроса. Отидете на Developer и изберете "Record macro". Опцията "Use Relative References" (намира се точно под бутона Record macro) в този случай няма да бъде маркирана. Чрез нея се указва дали нашите действия да бъдат с релативни или с абсолютни позиции. Ако са с абсолютни, макроса ще записва точните клетки където извършваме действието и ако после го приложим, той ще извърши действията точно в тези клетки. Ако действията са релативни, при прилагането на макроса действията ще се извършат относително спрямо мястото на клетката, която текущо сме маркирали. Понеже ние ще правим заглавен ред, който е винаги най-горе на таблицата, ще запишем макрос с абсолютно позициониране.

record-macro

Ще излезе диалогов прозорец, в който трябва да зададете име на макроса, бърза клавишна комбинация за неговото стартиране (ако желаете да има такава), местоположение за запазване на кода (ще го запазим в This Workbook, т.е. текущия документ) и описание по желание (то ще бъде добавено като коментар във VBA кода).

record-macro-dialog

Сега започваме да пишем нашия заглавен ред. Добавяме текст за колоните, формулата за средния успех и накрая оразмеряваме колоните, както е показано на картинката по-долу:

recorded-macro

След като извършите всичко, натиснете "Stop recording" от Developer менюто. Вашият макрос вече е записан. Нека видим какъв код е генериран. Отворете VBA редактора (ALT+F11). Ще видите, че под обектите се е появил раздел "Modules". В него има един модул с име "Module1". Отворете го и ще видите генерирания код:

macro-code

Самият код е доста описателен. Range("A1").Select казва "маркирай клетка A1". ActiveCell.FormulaR1C1 = "Име" означава, че в активната клетка (това е маркираната клетка, т.е. A1), формулата трябва да стане текста "Име". Нататък нещата се повтарят за следващите клетки.

По-особеното идва при формулата за средния успех. В Excel я написахме като "=AVERAGE(C:C)", а тук е записана като "=AVERAGE(C[-1])". Това е конкретна особеност на Excel и е свързана с т.нар. R1C1 нотация. Стандартно ние се обръщаме към клетките първо с името колоната, а след това с реда - например клетка C2 ще е клетката на колона с име C и ред с номер 2. При R1C1 нотацията ние първо се обръщаме към номера реда, а след това към номера на клетката - т.е. при тази нотация вместо клетка C2 вече ще пишем R2C3, защото е 2-ри ред и 3-та колона. В случая R е префикс за Row (ред), а C за Column (колона). Ако поставим ъглови скоби и число, ще имаме релативна позиция - числото в ъгловите скоби указва с колко напред/назад (при редове) или нагоре/надолу (при колони) да бъде преместена текущата позиция. Нека например се намираме в клетка E1 (Range("E1").Select). Искаме в нея да има формулата C2*10. Ето вариантите за реализиране на това във VBA:

  • A1 нотация:
    • ActiveCell.Formula = "=$C$2 * 10" - добре познатото ви изписване с абсолютна позиция
    • ActiveCell.Formula = "=C2 * 10" - добре познатото ви изписване с релативна позиция
  • R1C1 нотация:
    • ActiveCell.FormulaR1C1 = "=R2C3 * 10" - ще направи позицията абсолютна, т.е. реално ще имаме A1 формула "=$C$2 * 10"
    • ActiveCell.FormulaR1C1 = "=R[1]C[-2] * 10" - от клетка E1 слиза един ред надолу (R[1]) и се връща два реда назад (C[-2]). Резултатът е с релативна позиция, т.е. в A1 нотация ще е "=C2 * 10"

При R1C1 нотацията ако пропуснем R или C, това ще означава "всички редове" или "всички колони". Е, от примера с нашия макрос, VBA е записал A1 формулата ни "=AVERAGE(C:C)" с R1C1 нотация като ="AVERAGE(C[-1])", защото в момента се намираме в клетка D2 и в случая C[-1] означава "всички редове" (R е пропуснато) и "една колона назад" (C[-1]). VBA винаги записва макросите с R1C1 нотация. Вие разбира се може да използвате тази, която ви е по-удобна.

Нека сега изпълним създадения макрос. Добавете нова таблица и от Developer менюто изберете "Macros". Маркирайте вашия макрос и натиснете Run:

run-macro

В новият Sheet2 автоматично ще се извърша действията от записания код.

Накрая, за да направим автоматизацията пълна, бихме искали да извикваме този макрос автоматично при добавяне на нова таблица в документа. Това се постига чрез създаване на събътие (Event). В случая събитието ще е за целия документ, т.е. трябва да бъде добавено в ThisWorkbook. Кодът, който ни трябва, е следния:

Private Sub Workbook_NewSheet(ByVal Sh As Object)
   With Sh
      Call MyHeaderMacro
   End With
End Sub

new-sheet-event

Workbook_NewSheet е запазено име за подпрограма - в случая това е подпрограма, която се изпълнява автоматично при добавяне на нова таблица (new sheet). В Excel има голямо множество от такива събития за всеки различен обект. Можете да ги видите като натиснете стрелката на дясното падащо меню над кода:

events-list

Ключовата дума "Private" засега няма да я разискваме. Подадения входен параметър (ByVal Sh As Object) e новата таблица - към нея ще се обръщаме чрез името на променливата "Sh". С блоковия оператор "With" казваме, че в момента работим с таблица Sh, а с "Call MyHeaderMacro" извикваме вече записания от нас макрос. Вече сме готови - автоматизирахме процеса на добавяне на заглавен ред в нови таблици на нашия документ!

 



Добави коментар

Адресът на електронната поща няма да се публикува


*