Automation with Excel Macros / Excel VBA - Beginner to Advanced | Steve Tran | Skillshare

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Automation with Excel Macros / Excel VBA - Beginner to Advanced

teacher avatar Steve Tran, Freelance Software Developer

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Introduction - Updated

      4:57

    • 2.

      1.1 Showing Developer Tab

      0:34

    • 3.

      1.2 Recording Macros

      2:41

    • 4.

      1.3 Saving XLSM file type

      1:10

    • 5.

      1.4 Viewing Your Code

      1:27

    • 6.

      1.5 VBA Editor Message Box

      2:47

    • 7.

      1.6 Cell Referencing

      1:50

    • 8.

      1.7 Naming a Cell

      2:25

    • 9.

      1.8 Create a Folder

      2:48

    • 10.

      1.9 Error Debugging

      3:31

    • 11.

      1.10 Writing Data to Cell

      1:02

    • 12.

      1.11 Variables

      1:13

    • 13.

      1.12.1 Basic Math Integers

      1:36

    • 14.

      1.12.2 Integer vs Long

      2:35

    • 15.

      1.13 If Statements

      3:14

    • 16.

      1.14 For Loop

      4:18

    • 17.

      1.15 For Loops Continued Automation!

      2:51

    • 18.

      1.A Class Project 01 Description and Tutorial

      14:37

    • 19.

      1.16 Esc Key to Stop Macro

      4:28

    • 20.

      1.17.1 Do While Loop Intro

      8:20

    • 21.

      1.17.2 Do While Loop Use Case

      9:07

    • 22.

      1.17.3 For Each Loop Intro

      7:46

    • 23.

      1.17.4 Variant Variable Type

      9:23

    • 24.

      1.17.5 For Each Loop using Variant

      4:25

    • 25.

      1.18.1 Object Variables - Set - Intro

      4:11

    • 26.

      1.18.2 Object Vars - Declare + Read All Files in Folder

      7:12

    • 27.

      1.19.1 Workbook Object

      11:11

    • 28.

      1.19.2 Worksheet Object

      5:40

    • 29.

      1.20 Reference Libraries Word Object Intro

      7:50

    • 30.

      1.21.1 Calling Sub From Another Sub

      4:56

    • 31.

      1.21.2 Call Sub with a Parameter

      7:52

    • 32.

      1.21.3 Call Sub with Multiple Parameters

      7:04

    • 33.

      1.21.4 Sub with Optional Parameter

      6:55

    • 34.

      1.22 Functions Intro

      5:19

    • 35.

      1.23 With Statement

      5:52

    • 36.

      1.24.1 Error Catching - Intro - On Error

      9:26

    • 37.

      1.24.2 GoTo - Code Bookmark

      5:27

    • 38.

      1.24.3 On Error Goto Bookmark

      8:05

    • 39.

      1.24.4 On Error - Persistence and Reset

      9:35

    • 40.

      1.C.1 Automate Creating Txt Files

      6:40

    • 41.

      1.C.2 Automate Rename Files Fix

      9:18

    • 42.

      2.1 Moving Data - Create Form Record Macro

      4:24

    • 43.

      2.2 Moving Data - Name the Ranges

      7:11

    • 44.

      2.3 Moving Data - Simplify Recorded Code

      5:12

    • 45.

      2.4 Moving Data - Paste Values Only

      4:19

    • 46.

      2.5 Moving Data - Without Copy and Paste

      3:35

    • 47.

      2.6 Moving Data - Writing to Next Row

      6:00

    • 48.

      2.7 Moving Data - Add Timestamp

      1:35

    • 49.

      2.8 Moving Data - Writing to Different Sheet

      3:59

    • 50.

      2.9 Moving Data - Tidy Up

      6:28

    • 51.

      2.10 Moving Data - Validation Before Process

      15:36

    • 52.

      2.11 Named Table Object (List Object)

      5:04

    • 53.

      2.11.1 ListObjects (Table) - VBA Intro

      10:39

    • 54.

      2.11.2 ListObjects - ListRows and Looping

      6:22

    • 55.

      2.11.3 ListObjects - ListColumns and Row Values

      7:32

    • 56.

      2.11.4 Excercise - Delete Certain Rows

      18:54

    • 57.

      2.11.5 Excercise - Delete Certain Rows Lvl2

      8:05

    • 58.

      2.12 Moving Data Add Row w ListObject

      15:46

    • 59.

      3.1 Quoting Tool Project - Intro

      3:41

    • 60.

      3.2.1 Quote Tool - Create Folder

      13:01

    • 61.

      3.2.2 Quote Tool - Check and Open Folder

      7:20

    • 62.

      3.3.1 Quote Tool - Add Line UI Setup

      3:24

    • 63.

      3.3.2 Quote Tool - Add Line New List Row Part 1

      13:14

    • 64.

      3.3.3 Quote Tool - Item Data Lookup

      10:43

    • 65.

      3.3.4 Quote Tool - Finish Basic Add Line

      7:43

    • 66.

      3.3.5 Quote Tool - Delete Line - Refresh Count

      17:45

    • 67.

      3.4.1 Quote Tool - Excel Output Template

      4:58

    • 68.

      3.4.2 Quote Tool - Excel Output Header Transfer

      9:55

    • 69.

      3.4.3 Quote Tool - Excel Output Lines Transfer

      13:36

    • 70.

      3.4.4 Quote Tool - Excel Output Save File

      12:58

    • 71.

      3.5 Quote Tool - Auto Outlook Email

      11:20

    • 72.

      3.6 Quote Tool - Customer Lookup Table

      5:20

    • 73.

      3.7 Quote Tool - Check Attachment Exists

      5:54

    • 74.

      3.8 Quote Tool - Add Total Price

      8:48

    • 75.

      3.9.1 Quote Tool - History Log - Start

      10:38

    • 76.

      3.9.2 Quote Tool - Log Header Info

      9:31

    • 77.

      3.9.3 Quote Tool - Log Lines Info

      9:03

    • 78.

      3.A.1 Automate Get Data From Many Files Intro

      2:43

    • 79.

      3.A.2 Loop through List of IDs

      10:22

    • 80.

      3.A.3 Loop Open Files and Get Data

      14:28

    • 81.

      3.A.4 Convert Tag Format and Test

      7:22

    • 82.

      3.10.1 Quote Tool Clear Form Button

      7:00

    • 83.

      3.10.2 Quote Tool Table Zero Rows Debug

      5:09

    • 84.

      3.10.3 Quote Tool Add Line Validation

      4:24

    • 85.

      4.1.1 UserForm Search Tool - Intro

      12:30

    • 86.

      4.1.2 UserForm Search Tool - Basic Filter

      11:14

    • 87.

      4.1.3 UserForm Search Tool - Select Item

      13:20

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

1,170

Students

8

Projects

About This Class

UPDATE: I have recently recorded a new introduction and added hours of new videos.  I am still planning to add much more content to fulfill my mission of making a complete library of lessons to bring someone from a beginner to an advanced VBA programmer.  I am currently working on the "Quote Tool" follow-along project that is Section 3.

I appreciate your patience while I continue to build this course library!

Class Description:

This class will introduce you to the concepts of programming and automation using Microsoft Excel with its' macro and VBA coding functionality.  The beginning is suitable for beginners who have never done any programming before.  It is an excellent introduction to Excel Macros and also programming in general with transferrable knowledge for other programming languages.

It will walk you through essential concepts and slowly demonstrate some powerful automation that this skill can bring to your clerical computer-based tasks. 

As the class continues, I will introduce increasingly advanced concepts.  I will bring you along as I create example projects that combine and utilize the concepts discussed in earlier lessons.

The approximate structure of the course is that the lessons at the beginning will teach you individual concepts shown by themselves.  These are the building blocks.  The later lessons will show example projects where I demonstrate and explain every step of building example tools that could automate processes at your business or job.

Please feel free to contact me with any questions and leave a review.  Thank you for any time you spend watching!  If you leave a question in the discussion, I'd be happy to answer it and maybe even record a video lesson for the answer.

Meet Your Teacher

Teacher Profile Image

Steve Tran

Freelance Software Developer

Teacher

Hello, I'm Steve.  I'm a freelance software developer who builds custom tools to support business process efficiency, automation, and analytics.

See full profile

Level: All Levels

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Introduction - Updated: Hey everyone. So let me start off with a rhetorical question, which is, why should I take the time to learn Excel macros or VBA, which is just the name of the programming language that macros are written. For. Very quick background on myself, I've worked over 11 years making custom software tools, but the place where I worked in 2021, I became a full-time freelance developer, creating tools to help automate and improve efficiency for a bunch of different types of businesses, which is still what I'm doing professionally now. In addition to excel in VBA, I have a lot of experience and other programming languages like Python, C-Sharp, Java, and even some experience in web development. So for example, JavaScript. But by far, I spent most of my time in Excel and VBA. And that's because it's one of the most universal tools used in nearly every business from big to small. And the reality is when I'm looking for freelance work, it's where a lot of jobs are. You probably clicked on this video because you're at least a little familiar with Excel. Because it's used by so many businesses, that usually means that it requires nearly no setup for both developers and for users. So as long as you have Excel installed, you're usually good to go. The macro automation tools and VBA development environment are built right into it. Getting a project off the ground is usually as easy as sharing a file with somebody. For a lot of people, the basics of how to click around that file will already be familiar with them. At your job, you and your coworkers might even already be working in Excel every single day. So to build an automation on top of your processes that you have now is pretty seamless. And you can of course, still make completely new tools completely from scratch. But when the person goes to use it, they'll already have that base level familiarity that makes it a lot easier for them to get used to the new tool and to reduce the amount of training they need to get comfortable with the new process. Vba is also much more powerful of a tool that most people may think. It doesn't just automate Excel, which is what we mostly know if four, but it can also have control and automate almost any aspect of your computer. So a lot of that you'll see in this class. Now if I've been able to keep your attention, let me describe the class a little bit. I first grade this course specifically for people that had never written a macro or single line of code in their life. That's still in here because that's where the lessons we'll start off. But I've decided to continue to add to this class. So there's content ranging from absolute beginner to intermediate, all the way up through highly advanced. So I'm going to try to make this a living class, meaning that I'll continuously add content and videos to keep improving on the class and improving it as a course that will take you from absolute beginner all the way to professional level advanced VBA programming. And if you're just interested in programming and maybe you want to get into other things other than macros and BBA. I think this is a great introduction to bring in a lot of the concepts that are transferable to other programming languages. If that's the road that you want to continue on, I'll have to admit that some of the recordings on here are the first ones I ever recorded of myself. So some of them are from over a year ago at this point. Hopefully you'll see that the sound and video quality gets a little bit better as you go. So forgive me for the rough ones. If you come across any in-between. Also, the class is set up in a way that you should feel free to jump around from video to video depending on what's best for you. The general structure of the class is that the early videos will demonstrate specific concepts that will become the building blocks for the fully functional processes later. So those are more focused on specific topics. Then the later videos, we'll have you follow along as I build, for example, projects that you might find useful at your business or as a great demonstration of the building block concepts that we showed earlier. For example, the project and releasing right now is a application that can automate a bunch of aspects of the quoting process for almost any business that does quoting, it's important to me that I show every single step of the process without any kind of infomercial style, constant fast-forward a couple of hours ahead, leaving you just kinda confused as to what happened in that gap of time. I'm going to show every detail here. And you can just use the fast forward if you want, which is nice and easy with this video format. Even from here, I'd recommend that you jump around through the videos that just kinda take a glance at the content on here. So as you go farther down through to the projects, you can get a hint of the type of content we'll be covering. And then you can decide from there, where do you want to start or if you want to jump around to different spots and work your way up to those more advanced videos. Especially if maybe you're coming into this and you already have a little background and the early videos are a little too simple for you. You can jump ahead to what will be more advanced projects towards the end. And with that, I really hope you enjoy these tutorials. Feel free to leave me any messages or comments or reviews. I really appreciate your time to watch these videos. Or if you don't watch them, I appreciate the time you took to even get this far in the intro. So thank you and enjoy. 2. 1.1 Showing Developer Tab: As you start to fall along with this tutorial and pull up Excel on your own computer. You might notice that you don't have a Developer tab here, like I'm showing on my screen. That's because by default the developer tab is hidden. In order to unhide the Developer tab. Go to file, down here to options in the bottom-left, Customize Ribbon. And then over here on the right, you want to check the Developer tab if it's unchecked, and then click OK. And then you should now see your developer tab, which will show you all these tools that you're going to use to create your macros. 3. 1.2 Recording Macros: I wanna show you guys how to use the Record Macro function. And this is built into excel and it's something I used a lot when I first started working with macros. So if you come up here to the top left, you'll see this record macro button. You can click that. And then this forum pops up and it asks you the provide a name for the macro you're recording. We're going to call it example macro and click OK. And you see that this button on the top left change to stop recording, which implies that you're recording right now. And that's exactly what's going on. Whatever I do in my spreadsheet here is being recorded, including clicking these random cells. You'll see that that's actually being recorded and you'd be played back later. I'm going to create something really simple here. So let's say I just do something like highlight these cells and I want to write a high message. And then what I just did here was all recorded. So if I go back to my Developer tab, it still has the Stop Recording button, which means that we're recording still, I can click stop. So if I come over here, I highlight these cells. I'm going to undo what I did here because we're going to play the recording back. If I go to my Developer tab, I click macros. That shows me the list of macros I have available. And so example macro being the one we record it, I'm going to click run. And there you go. You see that it just played back the actions that we recorded. There's a really simple example of just how you can take a list of actions and play them back and perform them in a click of a button. And in this case not actually a button, but I can show you how to do that too. So I can come up here to Insert list. Here I have a bunch of components for forms. And the one I'm going to use here is the button control. And I'll click that. And I can just drag and drop a button here. If asking me which macro I wanna run with this button, I'm creating a quick example macro. Click OK. I can change the text here. And then if I clear this again, click, say hi. You can see it runs the macro. And I'll just do this again. We're going to record another macro that clears this out so I don't have to keep manually doing that will just leave this as macro for we're recording. I stopped recording. I go to insert, create another button, drag it, have it run macro for. And there, yeah, now you have two buttons. One that says hi and a second one that clears IT. 4. 1.3 Saving XLSM file type: I made this basic macro here where you click the say hi button and it shades in all these cells, so it gives you a high message. And then when you click Clear greeting, it'll just clear that out for you. So you can use this back and forth. And then now I have my file and I want to save this file. If I go up here to the top left and click the save button, I see this message here. And it basically tells me that I'm saving this file as an XLS file type. And so that's the default for an Excel file. You can see that up here into header. It's basically telling me that this is a macro free workbook file type, which means that if you save it like this, the macro that I created isn't going to be saved If I click Yes here, next time I open up this file, the macro that I created is going to be gone. So I'm not gonna do that. I'm going to come over here. I'm gonna click No. So it's going to bring me here to the save as menu. So if I come over here to this drop down, I can click this and select an excel macro Enabled Workbook or an XLS file type. I'll click save. I don't get that error message. And this is a file type that when I bring this file back up, or macros will still be in here. 5. 1.4 Viewing Your Code: In the last video, we went over using the Record Macro function up here on the top left, you might be wondering where the code go that we've recorded. How can I make an edit to that if I wanted to. And so that way we can view that macro is, and go up here to macros. You can see example macro is what we recorded. If you click edit, that brings you to the code editor so you can see what we recorded here. I clicked into the K4 cell. I changed the background color of that cell to black. I started copying and pasting that cell till I made this high message over here. So another way I could have gone to the code is just coming over here to Visual Basic that also opens this code editor. And then I can navigate through here once I get here. And then the third way I typically get to my macro code is if you highlight a button and a trick here is if I click this button, I'm not going to just highlight the button. I'm going to run the macro. And since I don't want to run the macro, I just want to highlight the button. I'll right-click this and then click out of this context menu. And then now the buttons highlighted without running the macro. Once this button's highlighted, I can come over here to view code. And that's going to take me directly to the code that the button was going to run. And here you are at example macro. And I'll show you again if I go to clear greeting, Go to View Code. That button was going to run macro for. And so there's a couple of ways where you can get directly to the code of your macro. 6. 1.5 VBA Editor Message Box: Now that we are looking directly at the code editor for our Macros, I can show you that the structure for each macro is written into these subroutines. So if I use an apostrophe character, I can leave a comment here. Macro code goes here. It highlights green showing you that it's a comment and it's not code that will actually run when you play this code that's written in here is in the language called Visual Basic for applications. And you can see up here this Windows called Microsoft Visual Basic for applications, typically people refer to it as VBA for short, VBA. So if there's something that you don't know how to do, the easiest way to do it is to just go to Google. And I do this all the time, even for things that I've done a 100 times. And you start by typing and VBA, and then whatever is you want to do. And so if I type in VBA message box, you can always try the first link. And you'll see you can easily find the code notation for whatever you wanna do. Some things take a little bit longer to find the answer to. But for simple tasks like this, I Google solutions all the time just because I don't memorize the notation of every single command in here. So here we want to look up how to make a message box. You see this notation is right here. We're just going to trust it will go over back here, type this. And if I wanted to run this macro, I can do so by coming up here to this Play button and clicking it. You go, you have the message box. I'll click OK. I'll highlight this. I'll make another line. Change this two. Here's another message box. And another thing you can do is instead of coming up here and pressing play, I can run this one line at a time and I can do that with the FAA button. And so if I press F8, you see this yellow arrow pop-up that tells me to line that's about to run. As I run that this first message box will pop up. I'll click OK here, it takes me back and then I can run the next message box. And then next step, the macro be complete. Something else I wanted to go over here is you might notice that the example macro is written in this notation where it says sub example macro, open and close parentheses, and then n sub. And that's the notation here because every macro is essentially a subroutine. And this editor will automatically handle that for you in some ways. So if I wanted to create another macro and I type sub example macro to, if I just hit Enter. You can see it automatically created the notation for you to be able to code and other macro right in here. 7. 1.6 Cell Referencing: As we create macros, we're going to want it to interact with our spreadsheet. So what you might have is a basic form. Let's say it looks something like this. We're going to want our macro code to be able to interact with this spreadsheet. And so if I come over here, I have this message box. I can change what that message box says. If I run it, it's going to say whatever I have written in here, I click OK. I'm gonna wanna put my name Steve over here in the message box. So the question is, how do I do that? I can use this ampersand sign to combine two strings together. And so I have the text, My name is on the left, and I want to get the value of this cell over here, and this cell is in between. Then I can do that by using the range function. And the range object is basically a cell or group of cells. And here in the parentheses is the name of the range. And you're gonna see here, after I type the range, I can hit period. And then this shows me this menu of all the different properties that the range object has. And there's a ton of them in here. And the one I want to use is value and you see it jumps down to that. And so that shows me that value is a valid property that exists. If I tab out of that here, we've updated our message box. So it'll take the value of the cell B2. If I run this. There you go. It says my name is Steve. One other thing I should show you is when I click this Play button, it's going to run the macro that my cursor is highlighted in. So if I click out of this subroutine and then click Play, you can see it asks me which macro I wanna run. Right now we only have one, but if I had a list of a 100 macros, it can't figure out which one we wanted to run because our cursor was not sitting in a specific one. 8. 1.7 Naming a Cell: Here over on the right, we have this basic macro that we created. It's just going to display a message box that says my name is. And then it references the cell named B ten. And that's over here. And click play. And there's the message box. So one thing I want to show you guys, and this is something that I wish I knew way back when I first started making macros because it would make my code much better and much easier to update, is the ability to give ourselves a specific name other than its default btn. And the problem with leaving the cell as referencing BY ten is that as you keep developing this file, this cell can move all over the place. And so for example, if I added some cells here and add a new row, this is now BY 13, but my code over here still says B ten. And so if I run this, it's not going to work anymore. And so how do I solve that problem? How can solve that is by giving this cell a name. The quickest way for me to do that is to select a cell. It's called be 13. Right now, I can come up here in the top left and just change it. I'm changing this cell to be called name. I hit Enter, it just registered. And if I click in the cell now you see instead of saying be 13, it says name. These other cells that don't have names, they still say their original address. But now if I go over here to my code and I changed my range name to be called name. I know I'm making this as confusing as possible right now. I can run this code. It's going to know the cell reference. But then if this cell moves around and I grabbed some rows, I delete them, I'm going to run this. And there you go, it still works. And that's because if I come back to this cell, when I deleted those rows, it knew that this cell is called name and it moves around with its reference. And I can see all these named cells. If I go over here at the formulas, I'll make this bigger for you and go to a name manager. I can see all the ranges that I've named in this spreadsheet. And so here you can see, again, as confusing as possible, The name of this cell is name. And it says right here that it refers to Sheet one, cell B21. And right now we only have one. But if you have many different cells that were given names, you'd see them all listed here. 9. 1.8 Create a Folder: I'm going to show you guys how to use a macro to create a folder. And I think this is a great example of how you may think of macros as something that automates your spreadsheet. But by using a macro, you can do things that you wouldn't otherwise do within Excel. Something like going through your file explorer and creating a folder. So I'm gonna come over here to my code editor on the right, I'm going to start a new subroutine. And I can type my macro name here. If you hit Enter, it'll automatically create an end to your subroutine. I can name this create folder. And now I want to add a line of code to be able to create a folder. And the create folder function is MKDIR. And you can see here as I open the parentheses, it's showing me first that it recognizes this function, which is a good thing. So that means that actually exists. And it's telling me that what it accepts within its parameters, within the parentheses after the function is a string and that string is the path. And so that's basically the address of the folder that we want to create. So the first thing I wanna do is just test out this function. And I already created a folder here. It's in the C Drive. It's called C Drive example, and that's where we want to create art. As I click back into the code editor here, it's just popping up this error telling me that this is not a valid line of code. Of course it isn't. It's because we left the window with the line of code half written. I'll click OK. I'll come back to it. It's a string, so we're gonna put it in quotations. We're gonna write C Drive example. That's where we want our folder and our new folder name we're going to call test, will close that quotation, close the parentheses. And we'll try this out. Hit play. And there you go, you see a new folder that was created called test. Next we're going to combine a concept from our previous video where we can create a folder based on the content that's in our spreadsheet. So over here back in our spreadsheet, I had already written this. I have this cell. It's called folder names. In here. It says Folder one. I can name this cell folder one. If I come over here to this string, I can use an ampersand to combine a string together. And I'm going to want to add range folder one dot value. And so now when I create a folder path, the path is going to be this all combined together. So C Drive example, and then the value of range folder one, which right now just says folder. And so if I go over here, I click into this macro, I run the code. I come back to my example folder and they go, we have another folder called Folder one. You see there is a space here which is the content of this cell. 10. 1.9 Error Debugging: In our other video, we threw together this quick macro where if I run this over on the right, it's going to create a folder based on whatever I have written in this cell over here, which is called Folder one. I want to show you guys what happens if there's an error in the macro. And what I know is going to happen here. If I run this again, there's going to be an error because it's going to try to create a folder in the path C Drive example folder one end because we ran this macro already. I know that there's already a folder there with that name. And so we're going to have a problem where it's not going to want to make another folder with the same name because it can't overwrite it. And so I'm going to run play. And you see this error message popped up. And it's telling you the error we have is path file access error, runtime error 75. I happen to know what this means and we already knew this was gonna happen. And the axis error is because it's unable to create the folder due to one already existing. Now if you guys didn't know what this meant, if it was a different era and you weren't sure what was going on, you could always take this runtime error code. I'll just grab this, I'll type it into Google and I'll put the phrase VBA until the beginning of the statement. And you'll usually find some sort of discussion or results about what the cause of this error might be. And then next, if you come back to the error itself, you have two buttons here really that you're going to use. If you hit end, it's just going to stop when it's trying to do. But if you hit Debug, it's going to bring you over to the line of code that caused the error. And this one's nice and easy because there's only one line of code. And so we obviously knew that this was the cause of the error. But if you had a macro with hundreds of lines of code, this would take you directly to the line that caused the error and highlighted yellow. Another good thing to know here, and I'll make this bigger is if you come to this screen, you'll see that this says break, and that means this is in Run mode when you have a yellow arrow here, that means that this is live and it's trying to run a macro or it's in the process of trying to run it. If you click play is going to continue down your macro from where the yellow arrow is. So if I click Play, this is going to continue to run. It still has an error here and I'll hit end. And so you see that break went away, and that means it's no longer trying to run a macro right now. So I can better illustrate that. I'm going to put debug print message here, one. And then on the other side of the statement, I'm going to grab this unquote message here too. And if I click run, we get the error again. I hit debug. And you can see we're on this line here where the error is. When I type debug print in a message. You can see it shows up down here when it runs that line of code in what's called your immediate window. And so if I hit stop and then run this again, it's gonna do the exact same thing again, is going to run this first line of code, gets stuck on the second line of code and there's your message. If I fix this problem, however, I can come over here. I'm going to take this folder, I'm gonna delete it. Now. If I continue running, I'm going to continue running from this line. We're not going to see message one here. The folder is going to successfully create and then we're just gonna see message two. And there you go. And these messages just the pen to the bottom. So you saw a message to show up here. We didn't get the error because there was no longer conflict and existing folders. And there's folder one again. 11. 1.10 Writing Data to Cell: Alright, so in another video, I showed you guys how to take text from your spreadsheet and use it in your macro. The opposite side of that, that I want to show you guys is how to use your macro and then write something back into your spreadsheet. So I can do that. If I take a range and I can take anything, I'll call it range be ten. And say dot value equals put text in btn. And I'll put that in quotation marks. And I run this. There you go. It's as simple as that to write taxed with your macro into your spreadsheet and combining some concepts together again, you can grab a cell. I showed this in another video. You can call it, let's call this phone. And then if I come over here, I can actually change range to phone. And if I run this, there you go. And place the value into your phone reference cell. 12. 1.11 Variables: What I've showed you guys before is how to reference information from the spreadsheet. So right here I have this example macro. When I click it, it shows me a message box and it takes the value of cell B1 from in here. Next thing I want to show you our variables that you can use directly in your VBA code. Because sometimes you don't want to pull information from your spreadsheet. There's information that you want to handle only in your code. So I'll come over here, creates a new lines. We'll clean that up. Denotation to create a variable is dim, variable one. As we're going to make this, a string type is string is basically text. And so now that I've declared this variable, I can now use it. And I can type variable one equals different text here. And it's now anywhere I use this variable, one will be referencing the string that we declared it over here. So I'll come over here to our message box. I can change this reference that is right now referencing directly to our spreadsheet, the cell B1. I'm going to change that to variable one. And if I run this, the other message box pops up with the value of our variable. 13. 1.12.1 Basic Math Integers: And our other video we showed you that you can create a variable. I first declaring it with this DEM variable as string. And then you can assign a value to that variable, and then you can use that variable. In this case, we put it in a text box. And so if we run this variable, one is different text here. Another variable type other than a string that you'll use very often are numbers. Very often you'll be using integers, which are numbers without decimal points. So we can change this to an integer. And since we've declared variable one is an integer here where we assign it some text that's not going to work. And so if we run this, you see we have an error. It's a type mismatch. And that's because we are assigning a string, a variable that is an integer type. And hit debug, it shows you the line that went wrong. We're just going to stop running this here. I'm gonna change variable one value to one. I'm going to create a new integer. And that's called result. And we can do some extremely basic math here. Result equals Variable one plus variable one. The result is the result. We'll run this. And there we go. We created a variable, assign it a number, did some math. And here's the result. 14. 1.12.2 Integer vs Long: This should be a quick video. And this one I just want to show you the difference between the variable types integer and what I'm more often used now, which is the difference between the variable type integer and a variable type. I'll set the new one here as long. In the last video, we introduced to the very basic ideas of variables and doing something with them. And I used an integer. But a lot of times you'll see me use a similar idea to the integer, but instead, I'm going to use the long variable type. And this is something that's very specific to VBA. If you get into other programming languages or you already have some familiarity with them, you'll know that integers extremely common. And it's used all the time. It's basically a whole number. But a quirk about integers in VBA is that they can only be values between, here's the exact numbers, but basically negative 32 thousand to positive 32 thousand. So I'm just going to demonstrate that here really quick. If I make this cell over here, 32 thousand, I'm missing a 0 here. And then I have this very basic code where I'm setting i as an integer and then setting I as the value inside cell A1. We set i and then we print it out here. Now that works fine. But if I come over here, just make this 33 thousand, which is pushing it outside of our range over here. And I run this, I get this overflow error. And that is telling us that the value of 33 thousand can't go into the variable I. So I won't get into the computer science of it all. Basically, if you are interested, you can read about it. It has to do with an integer being a 32-bit storage type. That's probably not what you want to get into right now. All you need to know is integer types have this limitation within this range of numbers it can accept. Now, meanwhile, along is the same exact thing. Only it can handle higher values. So if I change this to j instead, which is the long variable that we created. Now, J became 33 thousand really easily, and it did our debug print here. So we're able to use these larger values when we use the long variable type over integer. So when you see me use this probably fairly often in the future, you'll know that it's basically the same thing as an integer. Only without this limitation. 15. 1.13 If Statements: Now we're gonna go over if statements. This is where we're actually adding some intelligence to our code, where the code is able to make a decision for us. What I wanna do is I want to have our code reviewed the number that's in this cell here, and then tell me if that number is greater than ten or not. And this is something that you can do with a formula. But I just wanted to show this as an example that you can do also through a macro. And with the macro you can build this up to become much more complicated than you can typically with a formula. So to ceiling is way higher. So I'm going to come to my macro. I'm gonna create a variable to hold our input value over here. I'm going to write dim input value as integer. Input value equals range B7 dot value. And now for our if statement, we're gonna type if and then notation for an if statement is if parentheses condition goes here. I'll come back and fix that. Then it doesn't like that because of course this isn't a real condition. And if, and so if we create our condition here, input value is greater than ten. Now we've created a conditional statement where we're only going to run the code that's in between the if and the end if, when this condition is met. And if we meet that condition, will give the result in cell B8 equals yes. And I'll step through this code. I'm going to use the FH shortcut. Where you go, we'll run this first line. We declare the input variable. We check the if statement, and we did not meet the condition here. And so we skipped over this line of code. Now, let's try a different number in here. We'll say 11. And if I run this again, and right there you can see since this condition is met, now we're in this statement and we're going to run this line of code. But we're going to have a problem here. And so if I come back here, but the number three and I run this again, they actually ran a random split seconds, so you might not be able to tell. But when we fall along, what we know happened is that the value three did not meet the statement. And so all it did is leave this value in here. We didn't add another yes, but you can't tell. So I'm just gonna put a message box here so you can see that it actually ran and nothing happened. And so we don't want yes. To stay in here. That's from the last time we ran this when the input was 11. What we're gonna do is we're gonna create an if else statement. With this else statement, the code that goes in here is going to be what happens if you don't meet the conditions of the if statement up here. And so if we don't meet that, we're gonna do the same thing. Equals no. And we'll run this again, complete. And you can see now when we don't meet the greater than ten condition, it runs this line of code, the else statement. And so if we go back to 11, run this again, it'll switch back and forth. 16. 1.14 For Loop: In this video, I want to show you guys for loops. And these were the automation really happens where you can accomplish a ton of actions automatically. And so first, I want to show you an extremely basic four loop. We don't even need any content that's over on our spreadsheet on the left. The for-loop notation is four. And then you need a variable which is essentially your counter. Typical notation is to just use the letter i equals 123, let's say. And then next I. And so I'm going to create a message box here that displays the value of i. And when we run this, the first time we go through this code I is going to start at one here. This is going to display a one. And then when you get to this bottom of the for statement, is going to increment the variable i by one. And then so it will come back to the top of the loop and it will run with i equals two. And it'll do that all the way until i equals three. And then it'll be the last time that this runs. And it will know to leave the loop after you reach this criteria over here. And so let me run this. Here you have your message box of i equals 123. And then we're done. Now I want to show you how you might be able to use something like this to interact with your spreadsheet. So here I have three messages. So I'm gonna create a heading for this list here, bolded control be control u. And here I have three messages, and I'm going to call this message list. Right now this cell here is named the message list. So I'm going to use that as a reference point. For now. I'm going to comment this out. And I can comment this out by putting these apostrophes over here. And that turns these green. It makes them comments so they're not going to run. If I press play again, there's basically no codes and nothing happened. Something I haven't showed you yet is that if I reference this cell message list, which again is sell eight over here, I can use this function that's part of a range called offset. And you see it gives you a row offset or column offset. And so from the cell that you're referencing message list here, I can give it a number which is my row offset, which tells it that you want to offset this cell by one, which will bring me down here to message one. Message popped up again and again because I left this line when it wasn't a valid line of code. I'll come back to it here. I don't want to move my column at all because we're still in the same column. If I typed one, we will be moving one cell over to the right. We'll leave that as 0 value. And if I'll wrap this in a message box again, so we get the CD output. I'll run this. And because we're at message list, we go down one row offset. Here we see message1. Now comment this out and we can use the same idea in a loop. I'll come down here. And the other thing I'll show you really quick as I'm typing in these apostrophes. A faster way is if I go to view toolbar and edit, this gives me this floating toolbar over here. I can drag this up top and this button right here, we'll comment or the one to the right of it. We'll uncomment a whole block of code. But so how can I use this offset that we just demoed in our loop? So in our message box, we know the value of i is going to run three times with i equals 12. And then three, we're going to add a cell reference just like above here, message list. And instead of putting one here like we did above, we're going to use the variable i that changes every time the loop runs. So I change this and make this an I. And so each time this loop runs through, the value in this statement is going to change. And so I'll run this here. First loop message 1, second loop message 2, third loop message three. And so as we take this idea and apply it to more complicated macros, you can start to see how these loops can be used to perform repetitive tasks. 17. 1.15 For Loops Continued Automation!: In another one of our videos, I showed you how you could use the macro to create a folder. I want to combine these two to show you how useful the for loop can be. And so I just created this example where if I run it, it's going to loop through the messages in each one of these three cells. As it goes through this for loop three times. I'm, I come over here. I'm gonna change this to folder list, folder one, folder to folder three. This is called message list. I want to delete this reference here and change this to be called folder list just for accuracy. I showed you in another video you can come to formulas may manager in this spreadsheet, here's all the named cells that I've created. Here is message list. I can delete this reference here. Yes. And you can see this cell name has gone back to its original a eight addressed. And so now I'm going to name this two folder list. I'll go back to my split-screen view. And now we can take the same concept before we had this message box. I'm gonna change this to make directory from our other video, you may remember that this is how you create a folder in our system. And the input to the make directory function is the path where you want the folder to be created. And so I made a folder already called C Drive example. That's the folder we want our new folders to be created. And this use the ampersand, combine our strings together. We need to change this to folder list. And when we're looping before, what we're showing is that every time this loop runs three times is gonna go 123. And these cells over here. And so now it's gonna do the same thing only instead of showing a message box is going to be appending those folder names to the path that's used in our make directory function. So let's give this a try. There you go. It looks like nothing happened, but that's probably because it ran so fast. It all just happen and we didn't hit any errors. If we come over to our example folder, there we have it fold or 123. And so I'll delete these. And so you can see this run in real time. If I run this, there's are three folders based on these names. And if we wanted to get really crazy, I'm gonna come here. If I grab this bottom right corner, I can drag this down. You see Excel knows that I'm trying to increment the number there, or at least it's guessing. I can have ten folders. I want to run this loop ten times. Will show the folder here. Hit run. And there's your ten folders. And now we're really getting going on the automation. 18. 1.A Class Project 01 Description and Tutorial: Hi everyone. If you've made it this far to this video, that means you've completed all the videos I've posted so far for this class of what I consider the introduction to Excel macros and getting started from having never worked on them before. I came up with this project which will incorporate many of the concepts that we went over in the other videos for this class. And so the project that I'd like to give to you guys is that I have a list of numbers over here. And with this list of numbers, I'd like you guys to write a macro that takes this list and transposes these numbers over here on the right. But to only bring the numbers on the right that have a value that is greater than ten. And in here you'll also have some other things, such as starting with the fact that this is an XLS file type. And you can go over the instructions at the top to give you some goals to go by and some hints as to what to do. I'll also ask you to create some buttons to run your macro to perform the task. And the also clear the list so you can run the task again. And then when the macros done running to pop up a message box that will let you know that the macro is complete. So that's the project for you guys. I'll attach this file to the class, and so good luck with it and leave any comments and the conversation for the class if you have any issues or questions along the way. And so what I was going to do is I was going to complete this assignment so I can post it as the answers for you guys if you need to follow along or need to cross-check. And I figured that I just film it while I complete this project. So if you guys don't want to cheat, you can stop this video now and go straight to the project. So now we'll go ahead and try to accomplish this project. I'm gonna come over to the Developer tab, go to Visual Basic. There's no module in here yet. And so in the class We actually had a module created from recording our first macro. Without that, I can right-click, go to Insert, go to Modules. And here you go, we have our code editor, which you guys, you've recognized them, the classes. I'm going to create a subroutine. I'm going to call it sort list. There's the subroutine. And so I want to reference this list. And I don't have a name for this cell, as we mentioned in our classes, we can reference this cell is just before teen, but I actually want to give it a name to give it a more decisive reference. So I'm going to call this number list. Just to prove that that works, I'm going to type value here. I like to use this message box that's just, just to check on my code. If I run this, there you go. We have number list, but we don't actually want to use that cell. We want to loop through each value of these cells over here. And so I'm gonna type offset. I'm just going to type one for now. And I'll run this again. And here we go. We have number nine, which is the first item in our list, because we are one down from the number list cell. Now I know that I'm going to want to loop through this list here because I'm going to want to check each value to see if I should move it over to the list on the right. So for i equals and I want to see how many times I need to run this loop. If I highlight this, there's a little Excel trick here. If you highlight this on the bottom, it gives you some basic facts about what you've highlighted. So the count is ten, so I'm going to want to run this ten times. I equals one to ten. So I'm setting up a loop that's going to increment i ten times. I'll tab this out and I will set an endpoint for the loop next, ie. And let's try this out. Nine. So I see the mistake I made here is showing a message box showing nine over and over. And I think this is going to run ten times because that's how many times the loop is going to run. So let's click through this. And that's because I left. This offset is one. And really I want this to be i. And so the value of i will change every time this loop increments the variable I. And so if I run this again, here's 9118 and they go, I can hit enter here. And you see we incremented a loop that goes through each one of these cells. Next, we know that we want to put our results over here. And so just like with the number list, I want to create an absolute reference for this cell. I want to give this cell a name. And so I'm going to call it results. And so just like we were able to use the offset function to reference these cells going down. We can do the same thing with our results list over here. Let me get a little more room here so we can view our code better. And so I can reference this cell right here, for example, by referencing range results. That offset in just like over here where we use the variable i to increment the list downwards, I can use I again, dot value. And so now we're talking about the value of this cell here. And on the second time the loop runs, i will be two and we'll be talking about this cell down here. And so just an example will make the value of the cell i. And so what I expect to happen is every time this loop runs, i is going to go from 1234. And that will also offset the rose down. So you'll have one through ten down this list, right? So we're going to open this up a little bit. Then let's test out this code here. And so we're going to hit Run. And there you go. You see that as this loop increments, it is placing the value of i as it goes through the loop into this list over here, because we are offsetting from the results cell, which is the top of this list. Now, we don't actually want these numbers in here. What we wanna do is be moving these numbers from this list over to this right list if the value is greater than ten. So let me create a little bit more room here. And so as a stepping stone, I'm not going to bother trying to figure out whether the number is greater than ten. Let's just add this code and we'll update it so that we just move these numbers over to the right list. We won't bother checking whether it's greater than ten. As I mentioned in my classes, I like to test the logic app a little bit at a time rather than just going straight for the final product. And so here we know we are setting the value of the list on the right, instead of setting it as just I, we know we're getting the value. We got an error there because this is not a valid line of code. We know where giving a message box where we have the value of the number list over here on the left. Here we're setting the value of the list on the right. And so if I combine these two, there we go. Now, the list on the right will just match the list on the left over here. And we're not going to bother showing this in the message box anymore. So I'm just going to comment that out. I can delete it later. And so let's try running this and see what happens. Alright, so you guys might be able to see the problem I'm having just as I'm sharing these windows left and right, my icons are disappearing up here. And that's just because I'm trying to see everything on the left and I'm scrunching everything up on the right. So what I'm gonna do is I'm actually going to delete these columns over here. And we'll just go from memory because we know what we're trying to do here so that I can show you guys everything on the same screen. So here I make this window wider. I see your play button again. Let's run this. And there we go as we loop through each row or simply placing the value of this cell into the cell on the right, and it goes down this list back and forth. And now we want to combine the if statement. So we have this code executing, which brings values from the left to the right, but we only wanna do that under certain conditions. And so I can create an if statement. Where. And again, I'm getting error messages because I'm leaving incomplete lines of code here. I can grab this, which is the value of the item on the left. And say, if we're grabbing this, I'm going to copy and paste it up here. And we want to say if the value of this number on the left is less than ten, close the condition. Then we're going to perform a line of code which is moving the number over to the list on the right. And we're going to end that with an endif. And so will clear that we'll try running this. And there you go. It looks like we have a successful macro here. But one thing we wanna do to clean this up, this is fairly long. And so I'm writing this statement twice here. And you don't really need to do this, but to practice one of the concepts we learned in our class. We can create a variable to hold this value. And then we can use that in these two places instead of the full statement of the range, offset and value. And so we'll declare a variable dimension. We'll call that variable number. And we'll call that an integer because none of these have decimal points. We'll call number equals. And we'll go to range, offset and value. Which is the number that's in each of these cells. And actually one thing I can do here, because this loop is going to run ten times. I don't want to declare this variable ten times. I only need to declare once. And so I can move it outside of the loop here. And now numbers declared only once, but each time this loop runs, the value of number will be reassigned to each item on this list as i increments through the list. And so these references here is the same as this. So instead of writing the full range reference, I can just write the variable number. And I can change that in these two places over here. And so let me clear this list. I hit play. And there you go. You see the same code worked only we simplified it with the use of this variable, the variable name, number. So that basically completes our macro. And so now we'll just tidy up with the other bullet points on this project. So we want to save this from an XLS file type, which is the default Excel file type. And we want to make that a Macro Enabled Workbook. And so we're gonna go to Save, Save As. And we'll change this to a Macro Enabled Workbook. And there you go. And now when I press Save, I don't get an error message telling me that my macro is going to be lost because of the file type. Next bullet is generating the macro. That's what we've already completed. We want to create a button that run this macro so that we don't have to keep going. The code editor and hitting play. In other way we could run this macro is clicking macros in running our sort list macro. But to make it even simpler than that is, we want to go to Insert, we're going to add a button here. We're gonna create that button. The macro we're gonna run is sort lists. But actually I want to show you guys, I can click OK here and that's going to make this button run the sort list macro. But if I want to change that, I can right-click this button, go to assign macro, and then I can change it anytime two will go to sort lists, click OK. We can change the text of the button to sort lists. And we'll try this out. I'll clear this, highlight the leet sort list, and there you go. Now we're running the macro from a button. And then the last bullet we want to do is to create a clear button. And so I have a little typo over here. I'll change that. We're going to add another button, will go to Insert button here. And this is why I showed you before that you could assign the macro later. We do not have a clear list macro yet. So I'm just going to click Cancel. It still creates the button but doesn't assign any macro. I can click this and it doesn't do anything. Will change this text to clear. And we still need a macro that's going to clear this list. And so we could go into the code editor and type out a new subroutine here. But what do we really quick and easy is if we just record a macro. So I'll come up here, I'll click the Record Macro button. It defaults to being named macro one, but I can change this to clear list as our new macro name. I'll click OK. I can take this list, highlight it, hit delete, which clears a list. Will stop recording. Now if we go to this Clear button, I right-click this, go to assign macro. Here we have our new recorded macro named clear list. I'll click OK and that'll assign the button to the macro. And if I run this again, there's our sorted list. It clear. And now the list is cleared. Sort list. Clear the list. Alright guys, so there you have it. There's the tutorial on how to complete our project. Hope you guys enjoyed this class. Please leave any comments and the conversation. Let me know any questions you guys might have as you're going through the class. Or any excel or Excel macro questions that you guys might have on any other topics. And I'd be happy to answer them. And it'll give me new ideas for more classes to create. Thanks a lot. Appreciate you guys taking the time. 19. 1.16 Esc Key to Stop Macro: In this video, I just want to show you a couple of things that might help you as you're programming and making mistakes and troubleshooting, which is how to stop the code in the middle of running. So what I set up here is a very basic loop. It has our index and it's going to count I from one to 100 thousand. And if I run this, what we're going to see is that it takes a while to run. And you might set up a situation like this intentionally or not. But you might do something where your macros running for a really long time and you've changed your mind. We've done something wrong and we want to stop what we're doing. So in fact, I'm going to bump this up to 1 million. So it's really going to take a long time. I'm gonna hit Play here. Then we can see that this is going to take a very long time. And so we want to stop. I just hit the Escape key. Actually. This is a decent example because it did not work. You see how this kind of became unresponsive in terms of windows, you can see you probably recognize this from just using your computer, that everything's frozen out right now. Basically, it's trying so hard to run that it's taken over your computer and now we can't actually run anything. What I was trying to show you is that if you hit escape while the code is running, then you're going to stop the macro in theory. But we do hit these situations where everything's frozen up and it's unresponsive. It's not even taking any commands when you press keys on your keyboard. It's just not receiving them. In this case, we're kind of stuck, to be honest. I'm gonna leave this demonstration in the video, even though it's not what I planned. And I think in this case, because it's so simple, it's still trying to do the work. So now it's just stuck in this really long process where it's doing stuff for a very long time. And eventually it's either going to crash the Excel program or it's going to just keep working on this and eventually it's actually going to count to a million. And then we'll probably see that over here in our immediates window. In this situation, we're kind of stuck. We could wait it out or we could do Control Alt, Delete and end the task. And basically forcing Excel to close. The problem with those situations, of course, is if you did not save recently than you might lose the changes you've recently been making. So I'm actually going to go ahead and end this. Let's close out Excel here. You can see Excel is using up all the CPU because it's still running this crazy loop. So this is a good demonstration of the situations that could happen if you accidentally create really long processes or write code that's not very efficient, gets into these loops, installs everything out. Now I'll show you what I actually originally wanted to show you, which is that as we run this loop, then if you catch a quick enough before it takes over your computer and stops receiving commands, that you can actually stop a macro that is currently running. And you can do that by hitting the Escape key. So it seems like if we let this run too long, it's going to take over my computer. But as I hit play, I can hit escape really quick if I realize it. And you see Excel was responsive at the time, and it's telling me that I interrupted process. And here I can hit End, which is just going to stop everything. Or if I hit the bug, it's going to stop right on the line of code that it was running. What we saw here is there's actually a line in these situations that goes too far and then the system could make Excel unresponsive, and then this shortcut won't work. But it's basically the escape key. Now another little situation that I think is worth showing is if I do a message box here and I hit run, I tried to click, Okay, if I hit Escape here, it's not exiting the code. Instead it's just exiting the message box. And I'm kind of stuck in this message box loop. In situations like this, I just hold down the escape key and just press it and hold it. And basically it's sending the Escape key however many times per second. And then it's catching the escape right in-between when the window is closing and the next one is popping up. So in-between that time, it's actually getting the escape command that we wanted Excel to receive. Meanwhile, while the message box was open, it was thinking when we press Escape, it was just trying to close the message box. So you can also hold down escape if you end up in a weird scenario like this with a recurrent pop up. That's all I wanted to show you for this video. 20. 1.17.1 Do While Loop Intro: One of the previous lessons I showed you a four index loop, which we already have a video on. And this is the most common type of loop, which is you have a for statement, you have a index counter which is typically called I. And then you go from, in this case 123, and it's going to loop and increment upwards one at a time. So if I run this with F8, you see we go through this loop. I equals one. When we say next I, that's going to increment I by one, so it's going to be 23. Then that is the end of the loop. Because I is going from one to three. We already know that you can change it to ten over here. And I'm just gonna go ahead and run it all at once. And it goes from one to ten. In this video, I want to show you that there are different types of loops. There's more than just what I'm going to show you in this video. But honestly, I don't use a lot of the other variations. But the other major one is the do-while loop, which doesn't have the word for in it. So that's just so it's different in that way. And I'll show you what's different about it. There's another one I use which will shoot another video about called the for each loop. But here I'll show you that do-while loop. And so it has a similar syntax where you have these statements that wrap your loop. And then in your indentation between those statements, what we're going to execute in that loop. But in this case, you see it's a little different that we still declare I. But here I set I equals one. Basically what's going to happen is instead of saying I is from one to ten, I'm actually just going to push this out. So it's not a distraction. We have a condition in here, and this loop is going to run if this condition is true. So this is more of a true false statement as compared to our for-loop, which doesn't have a true false statement. It has a counter that goes from something to something else. In this case, we're going to recreate what we showed in our four index loop, where we have a condition where we're going to run I is less than three. That'd be similar to overhear. But what you'll notice is in this loop itself, it's going to run until I is less than three. But it does not say outright what I starts as, as part of this loop statement. So what I have to do is outside of our loop statement over here, I'm telling it that I starts as one before I even say anything about the loop. So it's outside of our code for loop, what the condition is being set up as. Now, if I hit F8, you'll see that i equals one. If I is less than three, we're gonna go into our loop. We are less than three right now. So we're printing it out. And then here I have to tell it to increment. Over here. We saw that I would increase by one whenever we hit this line of code. And instead, that's not going to automatically happen here. We have to write our own line of code to increment I by one. You see here as we loop through three. And then now as we go through I equals three, sorry, I equals three when we last did the debug print over here. And then we add one more to I, making it for at this point in the code. And then it's going to jump back up to check this condition. See that it is not true. Then jump out of our loop. Then with this setup, we can do the same thing we did before, which is change this to ten just as a demonstration. And if I hit Play, there we go. One through ten. Just got mixed up just because I had inflammation in there already. But if I hit play, we go one through ten, just like we did with our four index style loop up here. But you can see in the way that it's written, the setup is a little bit different and what we have to do is a little bit different. Now there are specific use cases where the do-while loop is really useful instead of the four index loop up here, which I can show later. But what I'll show you now is a reason that I generally default to using a for-loop over the do-while loop most of the time. And the big reason for that is because this is going to loop until this condition is false. So it's going to keep running. Whatever this is true. I have a line of code here where I incremented i. But I want to show you if I come over here and forgot to type that line of code and I hit F8. So I equals one here and I'm stepping through the code, I is less than ten and we print out here. We're going to check whether I is less than ten, which it is, because it's still one. We print out here. If I just keep looping through here, you see every single time I is equal to one, we're looping as long as it's less than ten. So this condition is going to go forever. I never changes. And the true or false condition over here is based on the value of I. So this is going to be an endless loop. I can hit F8 forever. So the do-while loop has this issue that's vulnerable to this endless loop over here. So you might wonder what happens if I hit play instead of hitting FAA. So let's go ahead and run this. You see this is blinking the number one here because it's basically just showing an endless column of ones. And now my computer is freezing up. Excel's freezing up. I can't click anything here. And this is well on its way to crashing. I won't even bother waiting this out and see what happens. But this will go as long as you're willing to wait basically. And eventually Excel's just going to crash and tell you that there's a problem like what happens when Windows stalls out. So that might happen on its own or you might wait five minutes like this, but it's going to go forever. The way out is the classic control alt delete. And then we're going to have to force shutdown Excel for this to actually stop. Or just wait forever really. This is the file that we were working in. I have this stuff set up for different demonstration later, but that is a big reason that I avoid the do while loop. If I don't have to use it where there's not especially a good reason to use it because it's really vulnerable to setting up a condition where you accidentally have an infinite loop. And if I use it, I have to make sure that you set up a condition that will actually change whether or not you get out of the loop eventually or not. Now that we have are increment of I in here correctly and our loops running like it should. Again, there's one little variation that I'll show you, which is that right now we have this statement over here, which means it's checking the condition before the loop starts. So if I said something like this, meaning we're going to run if I is less than or equal to 0. And we know that AI is going to be one up here. So if I hit F8, I equals one in this condition is false right away, one is not less than 0. So you see it skips out of loop and just nothing happened at all. Another variation of this is I can take this while statement. I'll cut it and paste it down here. And even though this statement isn't met at any point in the code, it's going to run our loop because it's not going to check this condition until we get to the bottom here. So if I hit F8, I equals one. And then we're going to perform this task and print out one. Even though I is not less than 0 until we get here. And then it's going to skip app. And basically whether or not you put this condition at the top or bottom, it tells the code when to check the condition. And the main reason to set it up this way is because you want this code to run at least once, no matter what the condition is, even if it's obvious, like what are simple setup has here, that the condition will never be met. So this code will always run at least one time before it stops and it doesn't end up actually looping. So that's the very first introduction to this different loop style that is called a do-while loop for obvious reasons here. And next is a little follow-up video where I'll show you the use cases, why you might want to use this specific style. 21. 1.17.2 Do While Loop Use Case: In the last video, I showed you the basic concept of a do-while loop instead of R for index loop, which we had an earlier video on. Here, I want to show you a use case example that will show why you might want to use a do-while loop for certain processes. In this case, I have a little bit of example data on our sheet over here. And what I'm setting up is a basic subroutine that's going to count how many rows are in here and tell us the number of rows in our data. So I've set up already a subroutine here that uses are for index loop, which brings I from one to ten. Then it is taking our range A3, so overhear and then checking using our index, I gotta go down each cell and check whether there's content. And it's gonna go down. And then when it finds a cell that doesn't have content, it is going to say that the last row is one above that. So in this case it's gonna go 1234. See that there's nothing here and stop and say, my last row count must be four minus one. And the answer is three. So that's what we're gonna do here. I'm going to hit F8 to slowly go through this at first. You see I equals one. I'm going to set this variable called test text as our offset value. So we have a three and then since I equals one to start, we're on this cell right now. And then it's telling us the text here is 162020, since it's a date. And then it's checking whether or not that they were that cell over here is blank, which isn't. So now it's going to continue to loop in step down. And then it goes down to the next one, which is 123. So it's not blank. It doesn't enter this if statement. The third one, same thing. And now what we know from here is we're on I equals for our text here doesn't show anything. And so we enter our if statement. The last row is I minus one. So three, we're using this exit for statement, which means we're going to escape our loop even though we didn't get from one to ten. Because we met this line of code. We're going to jump out of our for-loop. And it says there are three rows here. So now if I stop and I hit Play again, it just happens really quick. There's three rows. If I did something like just add another value in here, I can hit play again. And you can see it says there's four rows. So that's the system here. Now, if I go over to this other sheet that I have, there's a lot more rows of information here. It's not so obvious, like we saw before, that there were three rows that we could just count ourselves. This is much more likely because if there's three rows, we don't need a subroutine to automatically count. I know that we could scroll all the way down and count it through Excel, but a lot of times we might embed a function like this right into our automation. So this might be one sliver of code here in pages of automation that needs to figure out the rows dynamically. So over here, you can imagine this isn't going to work anymore because our for-loop goes one to ten. And if I hit Play here, you can see it says there's 0 rows. And that's because we're going from one to ten. So 123456, all the way to ten. And we never hit a scenario where the text is blank. Then so by the time this loop is done, we've never hit the scenario where the text is blank in the cell. And so last row just never gets set as anything other than 0, which is its original default value. You can have this situation. And the big thing here is we don't know how many rows this goes down. And so we have this loop That's forcing us to tell us how many times we can loop. There's a benefit of the for-loop because we don't have these infinite loops that we created in the last video, because there's always an end to this loop. You basically always have to tell it where it starts and where it ends. So now we could do something like a thousand and we'll try to run it. So we just pick a huge number to check how many rows and we still get 0. And that's because there's more than 1 thousand rows in this table into the same problem that happened at ten is happening at a thousand. So what we could do is just make this some giant number. We'll call it 99 thousand. It's running. And we're at 1290 rows here. And we come down here. 1293 is our Excel row. So that is the right answer. But we had this problem where we didn't know what the end cap of this for index loop needs to go to. And we don't want to always just make up a number, although that's a completely fine way to do it. You actually see at some points in videos I've already recorded that might be farther in this class that I use this method over here. Because it works fine if you know that you're never going to hit over 99 thousand rows here, this is a fine way to do it. And then I still avoid that problem. I showed you in the last video of accidentally making an infinite loop. The reason to use a do-while loop, which I have set up here already, is because I don't have to make up a number of how far this will go. This loop will happen indefinitely, and I don't have to put an end cap of when to stop searching. So when you don't know when you want the loop to stop, the do-while loop is just going to keep checking. And so I set up this algorithm. Well the FAA through, which is doing the same exact thing with a do-while loop. And I'm doing this while my test text, which is checking the information in our cell, is not blank. And so it's going to keep looping while it's not blank. And then as soon as it finds a blank, it's going to stop. One little thing I had to do here is start. The test text has a start. And that way we actually would meet this condition down here. Another way I could do this is to move this down to the bottom, just like I showed in the previous video. So of course, there's a bunch of different ways to set up these algorithms. This is going to keep looping. It's doing basically the exact same thing, which is going down each cell. In here. We have to have a line of code that increments i ourselves. But it's going to keep checking these. And if I hit the play button over here, it's running all the way to 1290, which again, is the right answer. So this is the most common use case, at least for myself, that we want to use a do-while loop. That's if we don't know how many times we want to loop at all. And we can avoid needing to have this situation where we need to come up with a huge number. And we just have to pull one out of thin air and make it up to assume that this is when we do assume that we need to stop and then we need to jump out of the for loop when we meet a condition. Because if we don't have exit for which is going to jump out of loop, this thing is going to go to 99 thousand no matter what. Because we don't have any code that's going to cut the loop short. So if I come in here and click, you'll see there's no more texts young here. And that's because it's still continuing to loop in debug, print out blank cells all the way up to 99 thousand. And in fact, this is going to last a long time. And so this ends up having its own susceptibility to mess up looping. And in some ways, the do-while loop here becomes the cleaner solution. And in fact, you see right here, out of habit, I wrote exit do, which is the same notation as the exit for only this is a do statement. So this will also jump out of the loop. But now that I'm explaining what I just did, I don't need the exit do while loop because by the time we hit this, the next time it comes around, then we're already going to test for this condition in jump out of the loop. So for example, if I hit F9 here and hit Play, it's going through all of ourselves. If found our last row, which is 1290, and then I hit F8, you'll see that we have up here to test the text. In that condition is false and we jump out of the loop. So in this scenario, I didn't have to put a line of code to automatically jump out of the loop because this condition was already met. Meanwhile up here, in order for me to leave this loop early, because we have this ceiling that the loop already thinks it needs to go to. We need to have this exit for wrapped up in an if condition. So that only in a specific condition, we exit the for loop early. That's it for now. That's the basic demonstration of the do-while loop and the most basic cases of why you might need to use it. 22. 1.17.3 For Each Loop Intro: In this lesson, I want to go over the four each style loop. So you see we have a loop here that says for each. In the previous lessons, we've gone over the normal FOR loops, which is the most standard where you declare a variable that's an integer. Or along. In this case, we usually use I as an index, but we use other letters or variables to. And as you go through each iteration of the loop, then our variable increases one with the first value all the way up to the last value. So if we step through this code here, I is one, and then the next loop, it is 234, all the way up to 100 here. And in this really quick example, I'm using our index variable to get the value of the cell that's in row I and column one, which you can see over here, is going to be these values. So when I equals one, we have cell value one, then 234. And that's because our row number is the variable that's changing through each iteration of. This is something we've already gone over in the past lessons. I'll just hit F5 and run this all the way through and we loop through all these variables. I'll clear this out now. There's this other type of loop that I use very often. It is called the for each loop, it's not used as commonly, so I'll explain it and show you the use case for it here. And here I already have a written where you have a object that's a range. Basically the for each loop, instead of having a index variable that counts from a lower number to a higher number. It takes in something over here on the right side of the statement, which is a bunch of objects. And then for each is taking a single object to get some real-world analogy. It might be something like if you have a brick wall, you might say something like for each break in wall of bricks. And then you have next brick is our notation here. And it's basically going to iterate through every unit in a group of units. Hopefully that makes some sense. I think this one up on the fly. What I have here is I have a range of cells. So cell A1 through a 100 is going to be all of our cells that have values here, which we already saw in our previous loop. And we created a object variable for a range here, which arrange is a cell or group of cells. So this expression right here, for each range, in this range, a one to 100 is basically saying for each cell in the range of cells A1 through a 100. And then we take this range and we're going to debug, print out the value. So if I hit F8 here, value one, and then the next time we go over to this range, we're basically in cell two over here because we're just gonna go through each thing. In this group of things. You see value2, value3, value four, and so forth, as I've looked through here. Now run this all the way through and you can see we go all the way to 100 because we've gone through every unit in this group of units, which is A1 through 100. I can even add here, maybe add some clarity is our range has all these different properties with it. I can say something like debug, print out our address. If I clear this out and hit F8 again, here's our value one, and you can see the range address is A1, A2, A3. Because we're going through each cell in this group of cells. The difference here, as you can see, that there is no index. And I'm not telling this loop when it needs to start and when it needs to stop. Like here, we need to say from one to 100 and we need to know is called our lower bound. Upper bound. But here the loop is just figuring out how many units are in our group of units over here. And if I did something like A1 through B10, 100 for example, I can do this. And let me stop this so we can start it again. Figure this out down here. We have value one and our dresses A1. Now we have a blank in our dress is b1. So let's come over here. A2, B2, B3, B3. And you see that this thing is making the decision on its own. A1 through 100 is this all the way down to 100? And as it's going through, each cell in this group of cells is going from here to here, to here to here and so forth. And it's figuring out what cells are in this group of cells. That's this range. We can run this. So that is the main idea of a foreach loop does just a quick introduction. You take your group of things and it's going to go through each thing. And then you can use this variable inside your loop is typically the reason you want to do this. And you don't have to worry about these numerical index numbers that we're using over here. It figures out this unit breakdown for you with the loop. Another use case here that I've prepared is just the same thing. I'm gonna do a index-based loop, which is the more common style. And another use case for the, for each loop. So here, if I come over here, you see I have these sheets, 12345 over here. I'm using my index. And if I hit F8 here, I made a typo over here. This is next, I see our next is always the thing our loop is based on. So since we're doing a for loop down here, I have to say next, I, if you come up here for each range, when I am ending my loop, I say go to the next range. Over here. Over here, this is going to run from I equals one to the count of worksheets in this workbook, the worksheets and then the number of worksheets, which we see over here is one through five. So if I run this, I equals 1234 and you see it's selecting these sheets for five and it's activating these down here at the bottom. And then the same concept with the cells and the range of cells that we did before. Instead, I can do this other notation where I have a worksheet object here. And then we're saying for each worksheet in our group of worksheets. So this over here means all the worksheets in our workbook. Then I can use this worksheet object here. And through each iteration is going to go through each sheet over here. And then when I say activate, it's going to activate that worksheet. So if I write here, Activate sheet one which is already activated now 2345. So that's it. That's just a basic introduction to the, for each loop. The magic of it is that it takes a group of things and figures out how many of the single unit is in there. And it comes out with that for you, much like our example up here, all we have to do is change our object over here on the right side of the foreach. And the loop itself would figure out how many subunits are in this group of units over here. So hopefully that made some sense. We'll add more to our explanation of for-each loops as we go. But this is a basic introduction of what it is. 23. 1.17.4 Variant Variable Type: In this lesson, I want to introduce you to the variable type in VBA called a variant. And to do that, I'm gonna do a couple of demonstrations with just what can go on with different variable types. You've already seen us use integers and strings, which is really common for variable types and every programming language really. So I've created a couple of them over here, two integers, and then this string variable over here. Then we have these variants which will set aside for now. You can see down here that I'm going to set our integer i1 equals the value of what's in range A1, which is one over here. So you see our integer one going to become range A1. And that works fine. You see I'm hovering over here and it says I1 equals one, just like we would expect from this cell over on the left. Now I'm going to take our text variable, which is our string. And I'm going to say equals cell A1 also. So if I hover over texts, you can see it also worked correctly. It is showing you that text equals one. But there's a difference here where you see over text, there's these quotation marks because it's a string. That's because a string can accept any characters, letters, numbers, special characters. And so there's a quotation mark showing that. Meanwhile, if I come back up to i1, There's no quotation marks indicating that this is just a numeric value. Which makes sense because I want is an integer, not a string. Now we have I2, which is a integer up here. And we're going to set that to be the value of cell A2 over here. And we expect that not to work. So as I hit F8, you see we have a type mismatch. That's because i2 needs to be an integer. But over here the cell is the letter a, so the value here and the variable type is incompatible. And so we get this type mismatch. So this comes up all the time. Then we would have to figure something out. Either this was a real use case. Either the wrong value is over here in cell A2 and we don't want that value there, or we didn't create this variable correctly and we should turn this into a string or something else. So that's this type mismatch. This is all set up to demonstrate these variants. So I created two variables that are variant types here. So v1 and v2. I'm just going to skip over this type mismatch line we have over here and jump over to v1. And they're both variant types. So you see I'm gonna do something with V1 and V2 here. And I'm going to set this V1 to equal the cell A1, which is the value one over here. I run that. And if you hover over V1, you see it became one. And it doesn't have quotation marks. So that tells you that it is not a string. So this is very similar to hovering over here to i1, That's an integer. Now on V2, we're gonna get the letter a here. So if I hit F8, you see how this works. And this is the letter a with quotation marks. So it seems like this is a string, just like our TXT variable over here. So that's kind of interesting. You see this doesn't have quotation marks or V1. And then this does have quotation marks for V2. And both of these variables are a variant type. And now I'm going to debug, print out this message here. And this type named command is something built into VBA that tells you the type name of the variable inside of its parentheses. So as I hit this, I'll actually just realized that I had left this debug print out. So if you saw that, that was a spoiler for what I'm about to show you. So if I run this, you see V1 down here is a variable type double. And then down here, the v2 variable type is a string. So that's interesting because we declared them up here, both as variance. What variants are, is an open-ended variable, which will become the variable type when you first use it. Basically, when you declare this, it's saying that you don't know what variable type V1 or V2 is. And then the first time you use it over here or here, it's going to try to figure out what variable type you want it to be. It's going to give its best guess in the side it for you. This is a workaround so that we don't have to know our variable type before we use it. That's what a variant is. It's open-ended. And then on your first use of the variable, it's going to try its best to declare that variable type. And you see after we ran these two lines, then it became a double end string respectively. So if I come over here and I try this again, Let's comment out this line that creates a type mismatch. Let's try this again. I'm going to run through, I'll clear this out. And you see the type here is empty because there is no type in empty again. Now as soon as you use these variables V1 and V2, in this case, it becomes a double and a string. And that's because when it sees this one over here, it's guessing that it's a number. Interestingly, you see it's making it a double rather than an integer. And so it's just making its best guess. And this is one of the reasons we don't always use variance for everything, even though it seems nice and it avoids our type mismatch error, it's going to make its best guess, which isn't always what you want. So when it sees one here, it's assuming that it's a double, meaning that it's going to be able to potentially have decimal points, even though there is no decimal points over here. And then it correctly figures out that for the letter a, it needs to be a string because it can't be any of these other number variable types. Now, if I did something like redeclare these, Let's try this again. So do this one more time and we'll follow it through its code. Let's swap these. So we're gonna do B and then two over here. And then we'll swap these two, A4 and A5. So you see we're kinda switching things is first-time v1 is a number, and then this next time V1 is going to become a letter. So let's see what it does with its best guess at the variable types. Come back here and we have our empty, empty. We set them as a, as one and a over here. So it becomes double and string. And then now we're going to set them as B and two. And then string in double. See they switched. And that shows you that a variant, once we declare it, it remains adaptive, even though we set it over here and the variant automatically guessed it's variable type. We can then switch that. It's not going to create a type mismatch like it does when we set a strict variable type up here for our standard variables. Now one more thing I want to test is I want to come over here and let's see how it adapts to excel over here. So right over here you see this is a number. If I type a, it's over to the left. I've got one, it's over to the right. That's because our cells are also trying to figure out what type of value this is. Numbers end up automatically default to being justified to the right of the cell. Now, if we come over here and we change this to a text cell type, you see our number one automatically justifies over to the left, just like the letter a would be, because text automatically justifies to the left. So now let's go back here and clear this out again. We'll run this. We have our empties. And now v1 comes over here and you can see there's no quotation marks. So we can already guess that our V1 type is still a double. So that shows you that it doesn't necessarily adapt to the fact that the spreadsheet over here knows that as a string or a text and is justifying it to the left by the cell type up here. Vba kind of work separate from that. So it sees the one over here, it's still making its best guess that a one by itself is a double and not a string. Which makes sense why it would think that. Now if you did something like turn this into one, e.g. we would expect that the a, that's part of it. You see, we're getting this error actually because this integer can't accept one. Let's just jump over here. And sorry, I'm doing a terrible job with these messages here. V1 is a string because one is not a real number. So that's it. That's how variants work. We don't overuse them because of this issue here where it's not very rigid. And that can make your code a little bit more unpredictable, which can cause some problems. Just like how you might expect the number one to be an integer or a long. And it's automatically guessing that it's a double. It makes things a little bit less explicitly controlled. So it's not necessarily something we want to overuse, but it has its use cases indefinitely in certain cases will make your life a lot easier. And we'll show some of those examples in the future. 24. 1.17.5 For Each Loop using Variant: The last couple of lessons, I purposely went over the for each loop and also the variant variable type. That's because I wanted to do this quick demo here, which combines these two concepts together. So right here I have the same demo that I made in the for each loop lesson, which is that we have a for each loop here and we have a sheet variable that is a worksheet. Notice that there's no S here, it's a singular worksheet. And we're going to say for each worksheet in all the worksheets in this workbook, you'll notice that worksheets here it has the S for plural. And just like our lessons, we can step through here and you can see we're activating each tab as we go through because this SH, object is incrementing. Keep running. This here is incrementing as we loop and so on the next loop it goes to the next sheet, the next worksheet, into the next worksheet. What we can do here is purposely mess things up. So I'm going to change this variable to be a range. Just like the example before arrange is a cell or group of cells. And what we expect to happen here is that VBA is gonna get confused because worksheets plural is made out of many individual worksheets. It's not made up of many individual ranges, at least not directly. And so we know that this plural worksheets has a bunch of different single worksheets in it. It doesn't have a bunch of ranges in it. And so we have a type mismatch, which we have right here. Now I'm going to stop this completely. And then of course, if we go back in our group of worksheets, we do have single worksheets. So if we have our singular worksheet over here, this is how it was working in our first example. We're back to working correctly. Of course, like we started. Now with our variant variable type. We went over that variance, we'll call dimension V as a variant. Here is a undeclared variable type that will just become the variable type on its first usage. Not actually its first usage on any usage, because we saw that it adapts even after you use it once. So if I take our variant variable here, v, Let's do this. And you see we got through here without an error and it's working just like when we had our worksheets variable. If I came over here and did it debug print four, we'll do our type name here, which we use in our last lesson. And we're going to check out what variable type V is. As we go through this loop, you can see we're activating the sheet. And again, I've left these messages up here. You can see that our VIE variable has become a worksheet object because the last time it was used was with this for each loop. And so VBA is again taking its best guess at figuring out what type of variable that v should be. And in this case, we're seeing that it can even figure out that it's an object variable, not just a integer or a string or a double or anything like that. It is using it. And realizing that in the context of what it's being used as, it needs to become a worksheet object variable. And so you see this keeps working. So this is useful because in some cases you might write a for each loop and you might know the object variable here that we're using, which is a group of things. But you don't know the singular object variable that this is made out of. In this example that I have, It's really straightforward. We have worksheets with S as a plural. And of course, in that is a bunch of singular worksheets without the S over here. So this one isn't really needed, but you will come across other object variables which are also plural, is a group of things that isn't so obvious. And in those cases, we can use a variant like we do here. Or if we want to be more explicit, you can even write a demo like I did, figure out that the object type is worksheet. And then come back up here and rewrite your code to be more explicit and specific in your call and create your worksheet variable. Now that we know that the object that we're looking for in our foreach loop is a singular worksheet or whatever it happens to be. That's it. I just wanted to put these two concepts together because I see them both as related. So these are two concepts that are both figuring out something for you that typically we're more used to having to figure out ourselves. 25. 1.18.1 Object Variables - Set - Intro: In this video, I want to introduce the idea of object variables. But we worked with before is typical variables. So I'm going to create an example, one that we've seen before, which is just a string that I'm going to say dimension text as string, text equals Steve. We even do something and we'll place this into a one. Value equals to dx, dy. Let's run this. I'll hit F8, will step through dX t equals t. And then here I'm sending it over to our worksheet in cell A1. So this is a normal variable that we declare. Then it can hold some information in this case because we call it a string type variable. Then it holds some text information. And then we can do stuff with this variable. Something we haven't covered yet is object variables. Object variables are a little bit different and it can be a very advanced topic and we can talk about it for a long time and all its details. But I'm just going to stick to a very high level right now in the context that we will use it as you're starting out doing automation, VBA. If we remove this, I'm just gonna clear this out here. And then we create a new variable called a range. And we'll say as range. This looks a lot like how we declared our string variable. And this is a range, and we worked with ranges. Ranges are a single cell or a group of cells. On our spreadsheet. We say range equals range A1. Let's say. And then I go to run this. I hit F8. We have text, and then we have our range. We see object variable or with block variable not set. And we'll see this all the time when we mess up our declarations like this. And that is because we cannot just say that this orangey variable is our range A1 because it is an object variable and not a standard data variable. When you have a object variable, you need to use this word set at the beginning. And that's the only difference we have when we're declaring this right now, for our example so far, I click this. We see we pass this line and we don't get an error just by using the word set at the beginning here, and we're done. So what does this mean? And why are these two types of variables different from each other? So we saw that we can do something with our text variable here. We can debug print and send it to our immediates window so we can see what that looks like. So now we have our text variable and we can do stuff with it. This very simple tasks like sending it over to our immediates window. Now, what can we do with this range object variable? You can see when I type this object variable range and put the period sign there, you see all these options pop up. There are different things we can do with it and different properties that exist for it. So I can do something very simple, like backup here so that we can see our options like I'm going to select. So we set our range to be A1, and then we can select it, which we're not gonna see anything because we're already in a one. But if I click out of here and move this cursor back up and run this line again. Here we're selecting the range. This range object variable has all these properties and methods that we can run against this object. Meanwhile, if we come back to our text variable, we put a period here. We see that we don't get a drop-down for all the different options we have. Because these normal data variables, their main function is just to hold some information so that you can use it again later. Meanwhile, these object variables are a reference to an object that has all these definitions built into the background already. And then all those definitions of properties and processes you can get to by doing these extra commands. And that's it for this video. I just wanted to be an extremely basic introduction to these object variables when we have to use the word set. And then we'll continue to build on this as we go forward. 26. 1.18.2 Object Vars - Declare + Read All Files in Folder: In this video, I want to go over kind of two separate things. First, I was going to make a demonstration that not only can we create files and folders, which I showed you in previous lessons. But I want to give you an example of a function here where we can take a folder and read all the file names that are in that folder. As I was trying to remind myself of how that code works, I just typed it into Google, basically typing in something like VBA, reading file names from a folder path. And I got code that looked like this. And if I run this here, I feed it a folder path that I have in here. And then if I hit run, it looks up all the file names that are in that folder. So if I come over here, you can see it is pulling the files out of this folder and placing them into Excel here. So you might find that useful for a bunch of different reasons. And this is just the start of getting the filenames. Another common thing you might need to do is open up every file in, do some automation that does something with all the files in that folder or some of the files in that folder. So that's what I'm showing here. You can look this up. And I'm not gonna go too deep into this function here that did this. You can also pause this and look at the code for reference and see how each line works. When I did this, it actually reminded me something I wanted to explain for the object variables, which was in the previous video. When I found this code off a website, maybe StackOverflow are another common website. What they have here, and you'll see this very often, is we're creating this variable. It's an object variable and literally it's as object here. And so this is just telling you it's an object, but not specifically what type of object it is. In the past video, we showed objects such as a workbook or a worksheet or a range. And we will continue to have that object is this broader category saying it's an object, then you can get more specific. And then in the very next line, we set this object into the specific object that it needs to be. So in this case, we are working with a file system object since we're going to read from our file explorer here. And you see we set our FSL object into create object scripting file system object. This lets us do things here. At the next time we see o fs o for our file system object, we're doing dot get folder. So that's what I showed you, happens when you use object variables is they have all these parameters and functions and methods built into them. And so now we're using that here. In the previous video, I went over this other notation. I didn't do this where we're setting the variable as a nondescript object and then using this create object line instead in the previous video, we did something like I'm just going to make basically our FSL object. I'm going to make this variable different just in this notation, but we'll do the same thing. And instead of doing object, you can see this says scripting that file system object here, five type script name. Nothing shows up here. That's because just like our previous video, we are missing our file system object in our reference library. So I wanted to tools and references. And if I come in here and scroll down to Microsoft scripting runtime here, and I add this, click the check box and click. Okay. Now just like before, I can do scripting and this showed up now, even though it wasn't there before. And I hit tab, and as I hit period, I have File System Object. Now at this point, I am already doing the same thing that these two lines do. In this line, I create the general object and then I call it a file system object from the scripting library. Here. I'm doing the exact same thing. I now have a object variable that is a scripting dot file system object. Now the benefit of doing it this way, which is what I showed in the previous lesson, is that because this knows what this object is and we added this reference library. Now, our code editor knows different things that they can do with this object variable. Because now it has the whole library about what the file system object can do. I can say things like get folder here and then you see it's showing up its list and auto-filling. I need a parentheses and it tells me I need to receive a folder path in here. And we're basically recreating this line. So let me move this down here. Actually, I'll just start over here. Get folder equals o FSL got. And then we have our folder path. So these two lines, now, this line and this line do the same thing. And the big difference here is that first I needed to add the scripting library when we go to Tools and references. So it takes a little more work to get started, is that I need to do that here in our editor. But once I do that, the benefit is that when I type dot FSL for here and hit period, I have all these features built-in already. Now, if I use the original, use this notation for our FSL object, which was created like this. Now if I hit period, you see it doesn't know any of the functions. Methods are parameters that are part of this object. And that's because when we are declaring this object variable, it has no idea what type of object variable this is. Then this setting to the scripting file system object doesn't happen until the code runs. So in this case, our editor, it doesn't know what type of object is actually is until it runs, and then it becomes the scripting file system object. In this notation, we added our reference library and now our code editor itself knows what this object can do. And then we get this option built-in. It ends up actually being the exact same thing. Only I like to do it this way because it makes it easier to write our code and do this editor and in this way makes it so you don't have to go to Tools, references, and add the library to make it work. So this is easier for that little bit of setup at the beginning. I want to make sure to cover this. Because if you are looking at code online, a lot of the times you will see users use this method. And now you know the difference is when you see the two notations that they mean the same thing. But you'll see this a lot when you are getting code from the Internet, people post it because it's easy to copy and paste and you don't have to explain to people that they have to add that library. And then once you get past that declaration part, the code itself ends up working exactly the same. 27. 1.19.1 Workbook Object: Now that we've done an introduction to object variables, I wanted to shoot a lesson to go over some of the most common objects, variables that we're going to work with in Excel. And you're going to recognize them right away. The most common ones will probably work with is workbooks, worksheets, ranges. I remember rages are essentially cells. So of course you recognize this as I say them out loud and type them that are workbooks are our Excel files or worksheets or our tabs here at the bottom and our ranges. So anybody who's worked with Excel has experienced working with these only we haven't really thought of them as object variables before. So let's start by declaring a object variable, and we'll say WB for workbook as workload. So what I have here is the file that we're working in is called main. That XLS file name that we're working in is called main. So if I say something like this, actually, don't even worry about this line that I added so far. I'd say Debug for it. And I say this workbook. And if I hit Control Space, you can see it's giving me these options to autocomplete the word, this workbook name. And I'm going to print that out. And so if I hit F8, we only have one line of code here. And the name of this workbook that we're working in here, and the code is main dot XLS m. Now we're going to come back here and we have this workbook object that I declared here, like we saw in our last lesson. If I type this in, say WB object is this workbook. And run through this, we hit an error right there because this is an object variable and we need to put where it's set at the beginning to create this cross-reference between WB, referencing this workbook. Now that I have that, we get through this line. And then when I look at the WB object name, here it is, it is main.xml SM. So it's the same thing when I typed WB is basically a shortcut to writing this workbook. And that's because I've bind that those two things together right here. Run that again and we see it is made. Something else I've done is over in this folder, I've created two other files here. I've just called it other file one and other file to Excel files. One thing you could take a note of right here is that these two are just regular Excel files. They're not excel ASM files to allow macros. They could be if we wanted to. But what we're going over is commonly used for you to use one Excel file, which is where all your code that does all the fancy stuff is. And then you might be opening up other Excel files that exist already and interacting with them or getting info from the other files. Maybe the other file belongs to somebody else or another department and you're trying to pull data from there. And so you're just opening that file and then pulling stuff into your main file. So over here I can declare some other variables. Say I mentioned WB to as actually I'm going to call it the workbook, WB. Wb. What? We want to set this as our other file, one over here. In fact, I'm going to call this though the other one. Just so we don't get confused with the name. I'm mixing this up over here. I'm actually going to call this WB main. Call this WE mean equals this workbook and then WB, other one equals. And then how do we connect these two here? We use this workbook over here, which is a built-in function in VBA. Here. Instead I'm going to type workbooks open. And then I need the path of this file over here, and that's what I place an open. I'm going to show you. I'm not sure if we actually need to put in the full path. Instead, we're just going to take this file name over here. And it may be able to detect that this Excel file name is in the same folder as our current workbook. So let's see how that goes and run through this. We're just going to set this aside right here. And you see, we didn't have to put our full path over here, just putting the filename made the first thing that it would check is the current folder that our main files in. Since these are all in the same folder, we could just put the file name and you see it opened this up. Now, if we come over here and say print w main, dot name, we have our main and we have the UV, other one, got name. And we'll check both of these out. What's interesting here is this file is already open. So let's see if this works. I have a typo over here. We have this command that opens the workbook. The Workbooks already open. So you can see it actually doesn't have a problem right here. There's a chance in some other instances that it'll throw an error because it'll say you can't open the workbook and run that command because it's already open. But VBA has that handled already, it realizes already open. And it's still going to set these two object variables as the correct files and connect WB other one with this other file, one Excel file. And let's check this out here. Here's our main, and then here's our other file as we come through here. Now, let's just add another one. So we have more work with will do other workbook to we'll set other q equals workflow stuff. Open. Another file, one. So S x has to be two over here. And let's run this and run it line by line again. W Main is this one other. You see it just blinked here because it's connecting our WB other one object, WB other two. Now it gets opened. You can see your file names up here. So we have three files open right now. And let's print out our names just to show you that they are now active objects of this started all over again. And we can print. Our immediate window is getting a little cluttered there, so let's clear it out. And we have all three of these files open. Right now. All we've done is print their names. But while this macro is still active, you see we haven't ended yet. So I can drag this arrow around. You continue running code. I can do things like activate. Our May workbook here. Other one that activate, that activate. And so now I have these three variables here that represent all three excel files. I'm activating our main file one here. And then other FiO2. Now we have these objects that represent three different files. And you can start to imagine how we can interact with all three of these files. And at the workbook level, essentially an Excel file, you can do all sorts of different things. But what I'll show you really quick is just an example of the sorts of things you can do that you might do with a normal Excel file, but now you have control of through the code. So now that I've got down here, we have objects for all of these. We can activate them. And then if you just type one of these, since they're all three workbook objects, they'll have the same properties, which basically means they have the same properties and the same processes that are attached to them. Routines and methods that exist for these types of objects, which is a workbook in this case. So as I type here you see all this stuff comes up. And I can do save, which basically means if I run this command, then it will be the equivalent of saving that file. You can do a Save As, and I can close them. So for example, I'll go ahead and close this. So imagine we do something with these files, we interact with data. I know these are all blank right now, but if you had data in all three, you could start to get data from one and move it to the other. And then when we're done some stuff, now we can go ahead and close the other file and then close the other file. So you see, we have a lot of control after we create these workbook objects, where we can use these objects almost like we have them in our hand and perform different commands with them. Another thing we can do is instead of opening a file that already exist, we can just kind of comment all of this out. Let's start all over here. We can say Workbook, new workbook. And instead of opening an existing workbook, which we did by file name before, we can say set WD nu equals workforce. Add. Simply doing this. Workbooks, that ad is going to create a new workbook, essentially an Excel file, and then set it to be our WB new object. So you see we have a new workbook that just opened when we ran that line of code. And not only did it create a new file here, we can say WB, new name. And as you expect, this is going to be book one, which is the name of this file, just as if you started a new workbook. So here's book one. Now we can start putting information in here. And we'll just kinda touch on the sheath, which we're gonna do in our next lesson. You can say sheets. One dot range, A2, value equals hello. Here's our new workbook. We're going to use that and we can start to call out this new workbook, recreate it, or use a one that we opened and start to interact with it. And then when we're done with this, we can even say WB knew that save. And we have just saved this file over here. It's probably in our default folder wherever that might be named book one. And so we can pass it even more properties. Save As you can see, if we do a Save As we start to get other properties like our file name. This example. Let's just say we can run this line by line. We actually create a brand new workbook here because we're running this again. We place Hello in cell A2, and then we save this as this is an example file. 28. 1.19.2 Worksheet Object: Similar to what we just did for the workbook lesson, we can also work with worksheets. So you have your larger Excel file that is essentially your container. And then within there you have multiple sheets. So I just added a new one manually here and you have Sheet1 and G2. We can set a new sheet object, which I'm going to call SH as worksheet. Very similar to the workbooks and continuing to show how our object variables, where I have to use the word set here. And I can say set sheet equals WB, which again is this workbook sheets. There's two different call-outs here. I can say heat too. And then now I have this worksheet and I can call it activate. And so now I've set SH as sheet two and then I can activate it. So if I run this xi2 and then as I activate it, we've activated G2. Here. I have different options that I can call in these parentheses here is I can call it sheet to buy the name or I can use an index. So if you see here, it says index, which whenever you see this, it usually means that you can use a number to call out the index sheet to here is actually sheet two over here, because it's just a number index that this is one and then this is two in sequential order. So if I'm over here, let's say I run this again, we activate sheet two. And in this case, it doesn't actually matter if I change the name over here because I'm not writing the name of the sheet, I'm writing the index number. So I come over here now. And new sheet to it's still this other tab when I activate it because it is the second sheet in the workbook. Now, if I switch this over here, for example, now this Sheet1 name is our second index. And so as I declare SH as that sheet, you're gonna see, I'll create a third one here. We're gonna go back to Sheet1 because one is actually index number two. And then so once we've done this, we've created this object which buys these together. And then just like workbook, I have different things I can do with this sheet. So now with this sheet, I have my range just like we saw before. I can say Hello. I can also have all these other things that you would manually do with the worksheet when you're clicking through Excel. So for example, I can say visible equals hidden. And then just to undo that, I'm going to say visible equals visible. So now I have this sheet object and I can do different things with it. Just like we did for our workbook objects. We can create many different references to different sheets, and that's how we're going to reference them in the code. So we can grab stuff from sheet two and move it to Sheet1 and vice versa, and create this web of processes as we're interacting with both multiple workbooks and multiple sheets. So I'll show you here SH is xi2. We added some texts to cell A2. We can hide sheet two and then making that visible equals visible. And we're gonna show it again. This might be the first exposure I can't remember from the past lessons. I'm going to show you something else here. Is if you're familiar with highest sheets manually, you would come over here and you can hide this sheet. And then sheet to, or actually I think it was Sheet1 is hidden here. If you go to unhide here, Sheet1, you can unhide it. One thing as I was just typing out this example that I realized is I can also make this sheet visible equals. And then you see it's auto populating three options that I have here, hidden and visible, which we've used and tested already. You saw that's what was visible here. There's actually a third option which is very hidden. So let's see what that does. If we go to very hidden and run that, you see it did the same thing as hiding the sheet. But now if I come over here to unhide, there is no unhide button. And if there were other hidden worksheets, and I showed this here, Let's say I hide sheet three also. I can come over here and go to unhide. And now in our list we have two sheets, hidden, sheet one, sheet three. But I can't see Sheet one on this list. And so a user who's clicking around on this interface that doesn't have access to the VBA code, doesn't even realize there's a sheet here, and that's what very hidden does. The only way I can show it again is running this line of code in VBA and I can't get to it through our user interface in normal Excel here. So as I run this line, we're going to bring sheet one back. It was always there, but just invisible to us. And the really interesting part here, I think, is that through VBA here in the background, you actually not only can automate what a person would do manually clicking through the Excel interface. But you're getting access to extra properties and functions that a regular user might not even have available to them. So when you're diving into this code, we have a long list of properties and this is just one example of functions that you could not even do manually unless you knew how to come in the background here and write the code in VBA for your functions. 29. 1.20 Reference Libraries Word Object Intro: In the previous videos, I showed that not only can Excel macros and VBA code that we've been writing control the Excel application itself. But it can also do things like create folders. So those were demonstrations that even though we are coding inside Microsoft Excel, that the code over here in our VBA can do things outside of Excel and control our computer. To continue adding to that, I want to show another example of this controlling another application and an application that often makes lot of sense for is for Microsoft Word. And Microsoft Word has its own VBA Editor and macros that you can work directly in Microsoft Word. But I want to show an example of how we can work from Excel, where we often do something like create a button over here. And we can make Excel itself control Microsoft Word. And then if you're working in a spreadsheet, you can make these programs interact fairly seamlessly. So I've gone ahead and started this test subroutine. The only thing here is test. And I want to show you a really simple example. I'm gonna come over here to the subroutine and I'm going to create a new object variable. We'll call that w, The doc or Microsoft Word document. We'll set that as an then if I type word right here, nothing comes up. That is because our VBA code over here doesn't have this command to work with Microsoft Word. And I'll show you how we can make some new options show up here when we're working in our VBA. We can do that by coming up here to tools. We'll go to references. And then in this is a giant list of reference libraries. Basically, they're almost like supporting extensions for VBA. So you see all sorts of stuff here. And the example we're gonna go to is if you scroll all the way down, it's an alphabetical order. We can land here on Microsoft Word object library. So these are extra tools that will allow us to have new features in our VBA that isn't out of the box. So if we click this, it's pretty close to out of the box. They'll all you have to do is click this checkbox. And if I click Okay, you can see we can continue typing here. And now if I type word than this exists, which wasn't here before, we say work period. And then in this case, I'm going to say document. So now our object variable, Word doc or a Word document object. And then now this is going to come with all sorts of properties and methods that we could call and use as part of the document object. Just like what we went over in our short lesson on object variables. And now that I have this Word document and let's set it as something, say set equals Word documents at. So basically we have our Microsoft Word application. Then we have our documents, and we're going to add a document in our document is essentially a file. So we are going to set our Word document as a new file that gets created. So I'll go ahead and run this. I'll hit F8. We're over here on this line. I hit F8 and it froze for a second there and nothing happened. I'm going to show you something else that's interesting here. I'm going to explain it first and then we'll show that that's what is happening, is that this did open a Word document, but it's invisible. So what we're seeing is that when you work with another application through code, it is different than clicking around on the user interface like we're used to in working with our computers. Instead, I just open a Word document, but it is hidden in the background. And you can't actually see because I wasn't showing my Start menu, but here's my start menu. There's no Microsoft Word application over here. And we can prove that because if I come over here and type in Word that application, that visible equals true, this is going to make the Microsoft Word application become true. And as I run that, you'll see Microsoft Word pops up. And here's a document that was sitting open in the background. Just to show you again, I'll run this. Sometimes there's an error box. I just ran it again and you saw it went away. I'm not going to get into those details until we need to in the future lessons. You see we opened a Word document. I'm running this again. So there's actually two documents. Now, let's make our Word Application true. And you see there's two documents open here. So what happened is we opened the document, we opened another document, and they're both existing in the background and we can do things with them. We could add text to them and start to format it like a Word document. And they're all invisible until I tell the program to make the application true. And then now if I do something like word, that application, a bowl is true over here. This is going to make the dock, make the word Application true. Let's do something very basic. What the document, which is to just save it. And you see we have the save as to command. I think the two is just because it's a second version. So this is your generic Save As command. You can see the parameter it wants to take in is the filename. So we need to create a file name in there to pass it in as a parameter. Let's say DEM file name as a string, filename equals. And I had queued up this folder over here, which is just a generic place where I've been putting some tutorial files. And we will say dot doc x is our file name. And we'll do the same as at our file name variable over here. And I will hit F5 for run. It's opening up a document here, test that doc. And then here is our test that document over here, showing a demonstration of how from Excel we can automate Microsoft Word. And so I'm going to connect this button over to our test subroutine over here. Let's close this all out. I just do a little bit of clean up here, will delete this document that we created. I'll come over here, I'll click this button. See, this is the era that showed up before. We won't get into the details of this, but it has to do with managing the Microsoft Word application that's open in the background. But we'll ignore that. And a lot of times this would just go away when you try again. There's ways to officially deal with it, but we just won't go for that level of detail here. This is just a proof of concept. So I click this button, Microsoft Word opens, it saves as test dot doc. And here it is in our folder again, all happening from Excel. And if we come back over here to our tools, we won't go over all of this stuff. There's endless amounts of information to go over here with just automation of Microsoft Word, which we will do future videos on. You also have all these other applications that you can work with in VBA, a far majority which I haven't had to use. But you just see that they are available here. And another one, and I'm sure we're going to use as Microsoft Outlook so we can start to automate emails. You'll see a library from Microsoft Outlook in here also. That's it for this one, we'll use these concepts in future videos. 30. 1.21.1 Calling Sub From Another Sub: Up until now, we've been making macros with what is one subroutine. So when we use this word seb here, that stands for subroutine. And mostly we've been putting our code inside our subroutine and then running it, whether we attach it to a button or just run it straight from here. What I threw together here is a simple macro here that counts from I equals one to five and puts a 1 second wait time in-between that. When I run this, I don't click Run here. You can see it counts from one through five and puts it over on our spreadsheet, and it's just a counter from one through five. What I want to show in this video is how we can use calls to subroutines in order to reuse code without actually retyping the code. If I wanted to do something in this case, like count one through five and do the same thing, but I want to do it twice. What I'd like to do is come over here and just do a copy and paste. So now this is going to run through twice, and I'm just going to put a message box. So we see a stop here once. And I'll even put another one down here. Saying, I'm running twice. If I run this here, we can see we have our counter of one through five. We have our pop-up. And then we start to run this exact same code again that we copy and paste that and we're done running twice. The problem here, even though this works fine, is that we have the same exact code in two places. And that's not a very big deal right now. But what if we wanted to do something twice and it was hundreds of lines of code, then we would have copied and pasted hundreds of lines of code in two different places that we now need to maintain. Our code is also much longer and that if we want to update it, we have to remember to do that in more than one place. And some procedures. You don't just need to run twice, you need to run many different times throughout your application. So what we can do here is create another subroutine. We'll call this subroutine sub count to five. Instead of copying and pasting this, I'm going to copy and paste this into our subroutine. So I am going to copy and paste it. Then I'm going to delete this. And what we haven't gone over yet is that these subroutines, not only can it be run directly from our spreadsheet with say, a button click or something like that. But it can be called by another subroutine. So now that we've created the subroutine called count to five, I can click this. Actually, I forgot to move this dimensioning of I over here. So we need to declare our eye up in a subroutine. And then now I'm just going to comment this out so we can see what's going on here. I'm kinda be inside the my macro subroutine. And when I hit F8 and run it, this count to five is going to know that this is a reference to this other subroutine. So as I hit F8 and step through, you see it jumps up to our other subroutine here. And then now it's going to start to perform our count to five subroutine. So I'm gonna go ahead and hit play and let this continue counting. So what you can see here is this is counting the five. I can even put, let's say Message Box about to start here. And then if I am in my macro subroutine, I'm going to click Play. It pops up my message box, and then it's running our count to five. You can see it's happening over here. We're calling this subroutine from inside another subroutine. And then you can just kinda run crazy with this and start to use these all over the place. So I could actually make yet another subroutine that calls the mind macro. And so you can kind of nesting these things together, which will save for another video for now, I just want to introduce you to this idea of how you can call subroutines. Then now if we want to go back to our original, I can take this and I don't have to copy all this code, which isn't much here. But again, this would work if this was a much larger subroutine with a lot of code in here, instead of having to copy and paste that more than one time throughout your code and make your code much longer and more difficult to maintain. I can just call this twice. So if I come over here and run my macro, I have about to start counting of five, which we're running here. We're done running once. And then it'll run the count to five again. 31. 1.21.2 Call Sub with a Parameter: In the last video, I showed you how you can call one subroutine from inside another one. So we have this basic counter over here where we have about to start. Now we're jumping up to our count to five here. Done running once, and then we're running our count to five again. One little detail I wanted to add to this is that you can pass parameters into the subroutine also, so that I can reuse this code. But I can also change variables within that code so that I can reuse it, but also adjust the way I use it slightly. And I think that'll make more sense when I show you this example. So we have this called count to five, and we're always counting the five each time we run this. Instead, maybe I want to count to a different number. And so how do I do that? If I wanted to count the five and then I wanted to count to ten. The straightforward way, but less efficient way is to make something like this and say count to ten. Now, I'm going to make this loop from I equals one to ten. And then I have to change this. So let's say if we run this, we have an issue here, count to ten. And that's because I used the word here. Instead of number. We continue running. We have about to start. We're going to count the five and then we're going to count the ten. But we just recreate the same problem we tried to solve in the last video, which is repeated code. So how can we make it so that we reuse this concept? We reuse the code in here. But we also have the ability to make an adjustment of what number we count up to. So I'm going to undo this. We're going to set this aside, so we'll just make this count to five again. So what makes it count up to five is this number right here. That is where our for-loop is going to run up to. I'm gonna make a new variable. I'm going to call it stop. And we'll call this along also because we're going to make this a number to change what value goes here based on what we want. So we're going to say stop at, then instead of counting to five every time looping from one to five, we're going to say boot from one until the stop value. And we have a total of what value. We call this count to five, but we don't really want it to stop there. We want to take, stop at whatever the user wants it to, or at least what we want to when we're calling this macro, count to the number. And we'll just call it that and keep it nondescript. And then so how do we from this routine tell it where to stop? So we're going to change these from count to five to count the number. We need to set stop. What I don't want to do is have to say stop at T equals five or stop at equals ten up here because that will make any sense. Now, we still haven't made the decision. We'd have to change the code here inside this subroutine that we're calling if we want to change the number. So instead what we're gonna do is up here in the parentheses, you may have noticed in the past that whenever we make our basic subroutines so far, we always have parentheses here, even though we've always left them blank. Instead. We can say stop at as long here. It actually, I made a mistake here because we say stop at equals long, we're declaring the variable up here. We don't need to declare the variable here. So I didn't need to type that in there earlier. I'll just remove that we declared in here. And what that means is whenever we're calling count the number, we actually need to put parentheses here. You see as I type the open parentheses, it tells me that I need to have a variable here called stop at. That's because it knows that this is referencing this subroutine. And then here is saying that we're going to use a variable called stop at and it's a lawn. So I can put a number in here. I'll say five in here. And then now, when we get to this line of code, we saw in our previous video that it jumps up over here. But then it's also going to take this five and the parentheses and set the variable that is an input parameter as five. So these are the input parameters that will go into the subroutine and stop at, will equal what we put in this parentheses when we're doing the call. Let me do the same thing here. And we'll run this demo. And in this case we want it to run ten. So now I can change this at ten and I'm going to step this with FAA, this macro. You see we have our message box. Now we're jumping up here. We pass the five through this parentheses. You see stop at equals five because this matches this up here. Now, when we're running through our loop, you can highlight this value and see that it's five. So we'll let this run. I just hit F5. It's counting to five and then it stopped. And then now it's doing the same thing. We should expect that the count to ten, because when we call it this time down here, we're actually passing the ten up through the parentheses when we run it the second time. So we'll just run that one more time so we can see that the first time we're using five, and then the second time we're using ten, because we are passing the value of the parameter through this parentheses when we're calling the subroutine. Just to show you, because I have this up here where it is expecting a value to be sent along with our call to a subroutine. If I remove the five here, it throws an error right away, even when I'm not running the code yet, it knows that this count, the number subroutine expects us to pass a parameter in. We call it. So right away and knows that I'm missing something here and you see that it's giving me an error, then that error goes away when I pass something in here. And if I pass, let's say a comma is our separator. So if I pass it two things, it also knows that it doesn't expect to. One last thing I can show you here is when we have the subroutine that has a parameter that's an input, the same way that we had an error when we try to call it without passing a parameter in through these parentheses. Since this subroutine needs to know what the value of stop at is supposed to be. If I come up here also, let me fix this really quick. If I come up to this subroutine and then hit play, you can see that it doesn't run and it pops up this window to let me choose which macro I want to run. And in here it's not showing count the number. It's only showing my macro because I can only run this macro if I'm telling it what the value of the input parameter is. And since this one has an input parameter, it knows that I can't run it without passing something through there. So it knows that I can't run count the number without specifically calling it from another subroutine or calling it from the code of another macro because I need this parentheses notation to pass in the value of the input parameter. So you see I can no longer run count the number by just hitting play or doing anything other than calling it from another macro so that I can pass in the input parameter here. 32. 1.21.3 Call Sub with Multiple Parameters: Since we've gone over calling subroutines with a parameter, Let's try making more than one parameter. So we have this stop at input parameter over here on our count the number of function. Let's add a second parameter. In case we don't want to start at number one, we can choose the range of the starting number also. Let's add a new parameter and we'll call it start at as long. And we separate them with a comma. So now there's two parameters that we can use here. And instead of the one that we were always starting at before, Let's change that to start at. So now when we call counting number, we can have a starting number and a stopping number. So let's go down here and update this. So let's say we want to do the same thing and do one through five. And we get an error here. Let's backup here. You'll see when I open the parentheses, it does know that it needs to input parameters here. So it's in bold shown we need a start and a stop at. So why does it throw an error here? This is a quirk about VBA and I can't explain all the details here from the computer science level. But what we have here is when you have more than one parameter, we don't need these parentheses. So the notation has two options. Either we can leave the parentheses off of this to pass two parameters, and this will do what we expect it to do. Or what I prefer to do is you can use this keyword call at the beginning when we're calling this other subroutine. And then if you use the keyword call at the beginning, now we can use our parentheses the way you would expect from before. So there's a little bit of a difference here when you have one input parameter versus two parameters, when you are calling a subroutine. I actually prefer to use call because I like to use this anyways, it lets us know that we are using a subroutine that we made ourselves. And it kinda makes it jumped out that you're doing a cross-reference right here. And then I think the parentheses make it a little easier to read what we're doing as opposed to not using the parentheses, but they both work and we'll do the same thing. So let's try this out now. Let's change this and then we'll have a break, and then we'll do something like 11. And we'll go to 15 over here on the second time we run. I'll start by doing FH. So we stepped through line-by-line. About to start. We'll jump over to count. And you'll see start at is taking the one from the first input parameter, and then it's respectively taking the second parameter here and populating stop at. And this would actually be the exact same process and we had a third, fourth, fifth parameter. So you can keep going here with the number of parameters that the subroutine will take as inputs. And then as we continue to run here, I'm just going to go ahead and press F5 and continue running. We see we count one through five and running once. So on this row of code here, we hit, Okay, we continue 11 through 15 and we're done running twice. So the main thing to show here is that you can do more than one parameter, but the notation changes a little bit when you're calling it on meeting this call keyword here, or which is demonstrated here, not having to parentheses when you're passing more than one parameter. So now here you see it doesn't even want the call keyword when I'm not using the parentheses. And then so we'll run this one's about to start. We have one through five here. And then we jump up to 11 through 15 here. As we've seen in our examples so far. And what I mentioned earlier is that as we're passing these parameters through, when we're calling the subroutine, it goes in order. So this one here is this parameter. And then the second is this over here. And if we had a third, just say this. As long. If I put a comment here, this will be a third. So you can see it goes in their respective order that the parameters are listed. I'm going to delete this here, but it doesn't have to be this way. So another way we could do this if we didn't want to call them in order. And it's not typically a big deal if you only have two parameters, but if you end up having a lot of possible parameters to pass through to a subroutine, then you might not want to call them in order. And instead, you see we have start on the left and stop on the right. We'd have this other notation where we type stop colon equals. Actually, I forgot stop at colon equals. And you see as soon as I type that colon equals, it bolds the second parameter, because since we are matching the name of the parameter that it, let's us call this or the clarity out of sequence. We can say five equals here. And then as I do the comma, now, neither of them are bold because I've kind of gone out of order here. So it doesn't know until I typed. And then it knows now by name that I'm using the right name start at is going to be this parameter up here. So we can do this in any sequence. And of course, if there's more than two parameters, we can call out one of the many up here and declare them out of sequence. And this will be useful in other ways later as we'll probably see in future videos. So now I have this and this is going to do the exact same thing. Only I was able to call them out of sequence. So we're counting from one to five here. And then we jump over here as usual and have 11 to 15. Just like what we demonstrated before. I can use the keyword call here. And then as soon as I do that, it's the same thing, but now I'll need to use parentheses. And this is more often what I would do is use the parentheses and the call keyword. This is a notation that you might see if you do something like record a macro and then do things in Excel. And then look at the code that was recorded from the macro, which we did in earlier lessons. A lot of times you'll see the recording will use this notation with the colon and the equal signs to declare the parameters. Something important here is just that this colon Gordon symbol here. So if I remove this, this isn't actually going to work, which might be a simple mistake to make a first if you're just typing, this is thinking that this would work. But you see it throws an error here. So in specifically this feature where you are calling a subroutine or function, which we'll go over in the future and passing parameters through it uses colon equals sign notation. 33. 1.21.4 Sub with Optional Parameter: Now that we've gone over the basics of passing through parameters to a subroutine call. I want to show the idea of an optional parameter. So what we've created so far, we have these two parameters that we're passing in, the start seconds and the ending seconds that we're going to run this timer. Something we can do with parameters is also to make them optional. So all I do is type this keyword optional before my parameter up here. And now I don't have to call these both. Instead, when I make this call to my count to number subroutine and I open the parentheses. You see we have a start at parameter, which is just like we saw before. But now our stop at Perimeter is in the square brackets. And that square brackets tells us that's optional. So we'll say start at one as usual, and then we won't type our second parameter in here. And we showed this in the previous video. But if I did something like this and just did one, I go to run this, you see, we have this message that pops up and it says the argument is not optional. It's throwing this error because it expects two parameters to be passed in per our declaration of this subroutine up here, but we're only passing one in. Now instead, if I type Optional on this second parameter, will run this again. And I'll do F8. As we step through here, we get our message, and then now we jump up here and start out as one like we would expect. And then we have this optional parameter. And we did not tell our call what we want the second stop at variable to be. And so it is 0 right now we highlight over it, which is the same thing that it would be at if we declared a variable and didn't set a value, just like we have our demise as long as I is 0 because we only declared it and didn't do anything. It's just at its default state, which is 0. Now stop at 0 because it didn't force us to pass it as a parameter. It was optional. And so it's just at its default value. Now if I hit F8, you see it's running the loop from I is one to 0, which actually doesn't make sense because it only knows to go forward. So the loop doesn't run at all because 0 is not higher than one and it's trying to increment by one upward. Now we're back over here. I'm just going to stop this. So this is how we can have a optional parameter in our subroutine design. Something I'll show you here. If I make both of these options, I can do that. Now, if I go here and open two parentheses, start at and stop at are both optional parameters and I don't have to call them. And just like you would expect, in this case, the parentheses actually goes away because I have nothing in there. But both of them would be at the value of 0. Now something to show you is if we did the opposite here, and I remove optional from our second, this is throwing an error. It's saying expected, the second parameter should be optional. And that's because it's confused by the idea that our first perimeter is optional, but our second isn't because it's so often that we call parameters in here in a sequence that they're listed. If I do something like this, It's very confused now because this one typically would mean our first parameter, but that's optional. And so it doesn't know that this one would possibly mean stop at. So you can just see there's like a logical issue here. And the programming knows that this is irregular and it creates a mix-up situation. And it's setting this flag where your mandatory parameters are always on the left and then your optional ones need to be on the right. So now that we've shown this concept, let's show how we might use it for something like that. And there's a lot of different uses for it, of course, but we'll show it how it could work for our timer here. So maybe we don't want our stop at to be optional. But instead, we have this timer that goes from one number to another. And we can do stop at as long and then start at is the optional parameter. So I need to switch the sequences that make start on the right so that it can be optional for the reasons that I just showed. Now, we could have something like we only pass in our timer. As let's say, we'll leave it at five seconds over here. But we could say from three to five seconds. Actually, sorry, I've switched these around. I'm mixing things up here where we're stopping on the first value. So this would be stopping at five seconds is starting at three. I'm just going to comment these out for now. So we'll comment these out for now. And then if I run this, I hit F5 and we see running 345 is how we're doing this. We can make it do something like since start as optional. If I don't have this, then this is actually going to run and we're going to start at 0 as our start at value. We can run this just to show that. So start at 0. And so we're going to see 0 up here, 0 through five. As we run this. We could do something like this. Since we know that if we don't pass in a parameter that this variable will start at 0, then we could make it say something like start at equals 0. Then we'll say start at I equals one. And that basically means if we're not passing in a parameter here, like we're not saying three to 5345. And we don't have to say what number to start at. And you can just pass one parameter and it will detect that nothing was passed in, so it's 0. It's going to start at one. You see it started at one over here. So this creates a custom server team where you can have the option to pass something in, but you're not forced to make a decision. And there is a default handling of a situation if we choose not to pass in a specific value for a parameter. 34. 1.22 Functions Intro: Now that we have a few videos on subroutines, how to call them from other subroutines, and how to use parameters. I want to introduce the idea of a function. So instead of sub here, something else we can do is use the keyword function. And we would declare it very similarly, and we'll just call it my function for now. Do parentheses here. With my function. I can also call that from another subroutine or another function. So basically within the code of a container, I can call this other type of container called a function instead of a subroutine. Now if I do this, I'm going to put in a message box here. I'll just put a random message box to see what happens here. And we'll run my macro. We get our pop-up. Now we hop into my function. You see here it's starting to look like it runs exactly like what we've gone over with subroutines in that when we call it, we jump over to this container of code and it starts to run. The main difference between functions is that you can declare this a lot like how you declare a variable and how we've shown that in the past. You can declare your function also as a datatype. And so we can say as string. And that means that this can also be used like a variable. Now, if I say my function equals Steve, let's see what happens here about the Start. Hello. And then my function equals Steve. And we haven't done anything with this, but if you now highlight over this, you see the value of my function is Steve. That example, we haven't really done anything with this function yet. So let's turn this into something really basic. This is like a classic example of a function. We'll say add two numbers and we'll have this thing taken parameters and the parameters. I won't shoot separate lessons on how to use parameters for these functions, because at its basic level, it works exactly like it did for the subroutines. We can say value one as long I will say value two as well. So this takes in two parameters, value one and value two, will have the result also be a number. So we'll make that a long also. And then here we'll say my function changes to the name, add two numbers, and this equals value1, value2. I suddenly have space here, which I shouldn't. Now when we call my function, not actually going to call it, I'm going to use this, like I'm using a variable. It's not my function anymore. Now let's call it add two numbers, and let's do a debug print. Now there's an issue here where light from our subroutine with parameters lessons, we need to send it in our two numbers. So let's send in our value one equals two, and then our second value will just make three. So we'll expect the result of five here. And I forgot to close that parentheses. And then we'll run this. Now we hop up here, we have 23 as our parameters that are placed into this function. And then here we're going to add it together. And then our function name, add two numbers equals five. You see we didn't have to declare it, like we declare our variables up here, because this creation of the function is essentially declaring add two numbers as a datatype here as a long. So now this ran, the result of this ends up being five. And so when we ran this debug print line, five came out here. Now the important part is that in order to have this output be five, we need to set the name, add two numbers. So whatever we have as our function name is what we need to set as the value. So if we did something like this and said, As long as result equals value one, value two. And I'm just going to comment this out for now. You can imagine that result equals five, but we haven't done anything to tell it that the result that's coming out of this function that we named add two numbers is going to be the result. When we hop over here, you see we have 0 for our output. And I'll run this. I'm just hitting F5 here. We're going to run this thing. We see 0 comes out and that's because we're calling add two numbers. And there's nothing that's making the result pass through into the value of add two numbers over here. If we wanted to do it this way and didn't want to directly do all our work in this function. We can say add two numbers equals result. So now we have five and then five becomes the output of this function. And then here's the five that shows up again. 35. 1.23 With Statement: In this video, I'm going to go over some quick coding notation. That's pretty simple, but we just need to go over it because we're definitely going to use it in the future. And I want to make sure you recognize it when you see it. So we're gonna go over the width statement demonstration I'm going to give is if I say range A15 value equals past, we've done something like this all the time. So I hit F8 and I run this and we've put the word test into range A1. Then maybe you want to do some more stuff with range A1 will say Range A1, that font, that all equals true. And then we wanted to do something else with it. Font, italic equals true. And then we want to say that that interior, that color equals red. So now if I come over here and I hit F8, and we run this, we have tasks that was already there. Bold becomes true, italic becomes true. The background apparently becomes black. That's because I use WD read when really I'm in Excel, so I should be using excel red. Let's try that out. Again. I hit F5 here, and there we go. So this isn't what's important. Why I wanted to show you here is that we wrote range A1 over and over again four times here. And potentially if we wanted to change ten more things weird, right at 14 times, this isn't the biggest deal, but the lines could get longer and this beginning tag and get longer also. So let's say we have sheet two and instead we want to say sheets to that range. Now this is getting even longer. Let's say we specifically wanted to call out this workbook. And now this is all going to work the same except if we have multiple workbooks open will be explicitly saying which workbook we're in and then which sheet we're in, G2, not to be confused with Sheet1 and our range A1. So now if I hit play here, you'll see it knew to come over here to sheet two. And the same thing has been added the sheet to. The annoying thing here is that we type all of this out over and over again. And if we have more lines, we need to do it even more and it's just redundant information. And if we wanted to change ourselves to B2, for example, we need to do it in four different places. Here is the with statement notation. So if I type width and then all of this information over here, I'm going to copy for now. And then say n width. Then what's in-between these two statements? The start of our width and then the end of our width. A lot like a if statement which we've used plenty of times. I'm going to tap this out so everything is more readable. And then I remove this over here. This width statement is saying we're going to use this as the start of the line. And then whenever you see a period over here that is going to tell it to pend this onto whatever we have for our width statement over here. That basically means that this is equivalent to this right here. I'm going to go ahead and copy this down just so we have it for reference. And go ahead and delete all of these over here. So these two things, this, in this mean the exact same code. There's no difference between this code except that this is a lot shorter. And if I want to change this over to say B2 here, run sheet two over here. I can step through this code and I didn't have to change this four times. Instead, we're working with cell B2. And you see as we stepped through, it's behaving as if these are just full lines of code with this period appending to this on the left. I'm going to stop here. That's really it. This is a basic width statement. I use it all the time. Saves you a lot of typing, saves you a lot of updating in the future. And you'll also see that sometimes when you record macros and do different actions on your Excel file and then view the code that was generated by your recording that the court had macro will also use this notation extremely often. One more thing I forgot to prove here is if you don't use a period, I can still come in here and say Range below that value equals something. You see here we're using B2, but because I don't have a period here, then Excel doesn't append this to what my width statement is about. So only if you start off the line of code with a period which you almost never do for any reason other than this width statement, is it going to take this period line and append it to our width statement. So if I come over here, I'm going to copy paste just to erase this here and run this line. Let's see, we're doing the same thing with B2. And then when we get to this line, it still works. It doesn't throw some error because it thinks it's doing something goofy like doing this. It is specifically looking for these lines that start with a period and anything else just acts normally as it would if it was outside the with statement. 36. 1.24.1 Error Catching - Intro - On Error: Okay, now I want to show you a basic introduction to error handling. In our past videos so far you've seen errors come up in our code. And these are called runtime errors, which is basically when something goes wrong in the code doesn't make sense. And so it tells you that an issue as occurred and stops running. And I'll make a very basic example. We'll say dimension, my number as a long, and this is a number value. If I say my number equals ten out my number. Let's run this. I'll hit F5 and you see here's ten down here. Now if I come over here and change my number to be Steve, I'll hit F8. So we run through this. We've seen this sort of thing happened. It's a type mismatch error. And it is because this variable can't accept the string, but I'm making it tried to equal a string over here. We hit Debug and we aired out over here. If I hit F8 to try to continue, we just run into this error over and over again. And we have to handle this. Typically when we get an error like this, this means our code is doing something that we don't want it to do. And so we have to come in here and change our code. That is still going to be mostly the case. But what we have the ability to do is to have our code recognized that the arrows are going to come up rather than hit while we hit now, which is everything just come to a grinding halt on this line of code. So I'm gonna hit stop again. And I'll show you what I mean by that. What we don't see going on in the background is that there's actually a variable called ARR for error. And you see how when I typed this, we have all of our properties and methods for the ARR object. I'm just going to call it the error object moving forward. And it's sitting here in the background. And I can say debug print that number. And let's hit F8. And we'd run this and you see, this came up, error number was 0. I can do something else like error description. And I'll move this up one and I'll hit F8 again. And you see nothing came up here. That is because this object is sitting in the background and there's no errors in our code up to this point, we know that we're going to have an error on this line of code, but we haven't run it yet. Now I'm going to type something here called on R. Now I'm going to type something here. I'm going to type on error. So what I'm saying is if there is an error, then we're gonna do something. You could change what happens here. But in this case I'm going to write resume next, which basically means if there's an error, then just continue going forward. So I'm actually going to stop this and then I'm going to copy this. Let's just look at all this stuff here. We're going to say on air. And then we'll go back to our number here. We remembered that there's, the error number up here is 0. In fact, I'll put even more debug messages to make it all as clear as we can. I step through this code, we have this error object which we never declared. It's just in the background of VBA when it's running. The number is 0. The description is nothing on every resume next, and this is where we expect to hit an error where that runtime error dialog was popping up before. And now if I hit F8, you see it went through it and then even pop up the error. So, so far we don't even know that something incorrect happened that we hit an error. Even though we already know that this can't possibly be Steve, this variable here. If I hover over it, you see it's still says 0, which is its default state when we declare it. And then now we have an error number of 13. And then when we hit my number is 0. So if I hit F5, you see it ran again and there's just no error. Let's make this more clear. Number description right here, every number, and we'll even do errorDescription again down here. And that is all because of this line right here where we're saying if there's an error, then we're going to resume next. And that is why we can continue. And even though we hit an error, you see this error object on this side of the statement reads the error that happened. It's an error 13 and a type mismatch. While before the error happened, this error object was containing nothing because at this point there was no error that occurred. Do something like just comment out this line. You'll see if I hit F5, we're right back to where we were before, which is that we hit this line. We have runtime error 13. So you can see this is the error number that happened down after our error occurred and it's a type mismatch. So the main idea here is there's this error object that is hanging in the background. And when an error occurs, the properties of this object change to what error occurred. And most of the time when everything's running correctly, the error number is 0, the description is blank and there's other tags that just show this error object at no errors have occurred. Now a common error handling situation you might find is you're going to say onError, resume next. And we don't actually want this to just continue and do nothing. Some people might do this, but there's considered really bad practice because something went wrong and you don't want the code to just ignore it. Because if we have hundreds of lines of code, all this stuff down here, if there was much more logic, we don't want to just continue and run even though something went wrong. That means R code that runs later might have something that goes wrong. And we want to actually know that something bad has happened. So a lot of times you have this resume next, and then we'll have something like if that number is not 0, then a condition. And then in here, just for example, Let's pop up a message box and we'll say ever occurred. And we'll say our number or distributor. What we have here is if I continue here, I'll actually have to start all over. So I hit F8 on our resume next, and then we hit our error here. And nothing has stopped us, we're continuing. But now we have this if statement that says if the error number is not 0, that means our system detected in there. And then now I had a message box. And if this macro was running from the user, you see we're getting a message box telling us that the error occurred. And the benefit to doing something like this, even just a pop-up message box is now I can continue running my code. I could do other things or fork the code in different ways. So that one thing occurs if there is an error, and another thing happens if there is not an error. And we can notify the user without that dialog box popping up. That might be confusing to the user. Now we can control our message of what the user sees rather than getting the default pop up. That happens when VBA detects an error. Now if we make it so there isn't an error. So let's say my number equals one, which should be a completely valid line of code we had on our resume. Next, if our number is not 0, then it's going to enter in here. But because this doesn't cause an error, we just skip over this and no error occurred. And you see down here, we're still at error number 0. So let's step through this again. We'll see even though we have this line so we're ready to handle an error. We don't use it. So error number is still 0 here and we never have to jump into this if statement. And we'll just go right back to what we were before. And you can see now with this code here, we can detect any problems that might occur on this line. So in this example, we're specifically trying to target this line of code because we think that there may or may not be an error that occurs on this line of code. So a lot of times you'll use this method just around the code where you think it's likely to have an error. What you shouldn't do, or maybe not likely to have an error, but there's a decent chance that you might have an error. And then complicated code, there can be all sorts of variables that are combining together. And so it won't be as obvious as us purposely creating an error here in a single line. Of course. A main idea here though, is typically, you see this notation wrapped around a very specific line or small chunk of code. What you wanna do, have hundreds of lines of code down and have this on our resume next, around all of your code. It might be tempting to do that in certain cases, but it's considered bad practice because you don't want to ignore all your problems and then have all sorts of downstream negative effects in your code without escalating that and letting you or the users see that something went wrong. So that's just the basic introduction here. As we go, we're going to build up much more detailed ways that we can use this error handler. But this is the basic concept of this keyword of onError. And then the different things you can do with this error object as you are handling the errors that might occur in your code. 37. 1.24.2 GoTo - Code Bookmark: Okay, if you just watched the last lesson on an introduction to error handling, I still have just the basic version of that code up on my screen. But I want to introduce another small topic before we continue on error handling. And that is the naming of different sections of the code, basically bookmarking the code, and then being able to jump to that bookmark. And in VBA, that is called the go-to function. Basically. Let me show you what I mean here. Now and at the bottom of our code, I'm going to use this notation where I'm going to call this section two. It needs to be a single word without spaces. So I'm using this underscore. I do colon here. When I hit Enter, you see the line automatically jumped over to the left. If I tap this, you see, as I change the line, it's still wants to move over to the left. And that's because this is a bookmark. Now type something like section view stuff. Actually tested this out right before I hit record. So I already have this message down here. And the only line here is a debug print. Now, if I run this, well, we actually still have our code from the previous video. But I had this error message that occurred were debug printing. So we're just running the code and you see, now we didn't run this line of code. This is against the left wall, and it is just the notation because of this colon that it is a bookmark. So you see it never ran that line of code. It just skipped over it. And now it runs this line of code and we ran everything all the way to the end. Now what this bookmark means is it just marks this line of code. It marks actually this line of code and it is a jump to everything underneath it. You can jump to the bookmarks, something as writing go-to. Section two here, you see goto is a keyword over here, and it automatically formatted and change colors here to show you that's a keyword. And then we have our section two here. So if I run this code, I'm hitting F eight. And on this line it says go to section two, you see a jump down to this section to bookmark. And now we're running the code over here. And we skipped all of this stuff here. And that's because this line of code just tells you to jump to wherever the bookmark is. Now if I do something like jump to section three, let's see what happens because there is no section three and you see I hit F8 and this immediately popped up telling you that it's not defined. Even before we start running, the code is compiling. And realizing that there is an issue here that we're going to have a go-to line that doesn't have an existing bookmark. But you saw before that putting the bookmark here, it doesn't cause any issues. If we're not using that tag doesn't actually cause a problem, even though we don't jump to it. But you can't jump to something that doesn't exist. In the next lesson where I continue working on the error handling details, you'll see why I'm showing you this here, because this Goto function is commonly used for basic error handling. One thing I will say is that this ability to Section two over here typically is something that's often pointed out as a problem in VBA, which is to say that a lot of programmers who do more modern languages don't like to use this or overuse it. One of the main reasons I use it will be the error handling. Then I'm going to show you later. But it's common for this to be brought up as one of the reasons that VBA can cause some code to be really hard to follow and hard to maintain. Because all of this just jumping around and skipping, which is just hard to follow. If I left this code here for whatever reason, you can see it doesn't make any sense. And that's because all the code in here will never be run. If I just left this like this for whatever reason, this was a function that was being used in something I created. It's not obvious now that we see what this goto and this bookmarking does, we know that this code itself will just never be run and it doesn't even make any sense that it's here. But you see it's not flagging us that this is poorly written code. In the worst-case is you'll see bad code where it has tons of these goto is all over the place. Typically how the code runs, which we've been doing so far and will continue to do is of course top-down that we just run one line of code as we go one by one from the top down is the easiest to follow. But once we start to get crazy using too many of these Goto statements, you can see that the code won't just be going top to bottom. We can be jumping all over the place. And if there's hundreds or thousands of lines of code across different subroutines and functions jumping all over the place. We can get really confusing really quick. And so even though this is a really simple function to use for a lot of programmers, it's considered bad practice. You'll find people complaining about this sort of thing and calling it spaghetti code because the code is so tangled that it's very hard to follow where each process path is going. That's it. There's a basic introduction to this Goto function here that we're going to use. But keep in mind that it's not something that you want to go overboard on using. 38. 1.24.3 On Error Goto Bookmark: Now, let's tie the last two lessons that I record it together, which is the introduction to error handling with this on error statement and this goto section over here, where we're able to jump to a bookmark. Right now, we have this example that really doesn't do anything. We have a variable called my number. And then we might create an error over here, which we're catching with our if statement over here. And then we're not doing anything interesting over here. We're just outputting the error. Now instead, let's do something with the code just to give you a use case example, where we have our number and we can say answer as, let's call it also. And we'll say answer equals my number plus minus. Say, debug, print. Answer. Our answer here. So if all things go well with the Coby have here, I'm going to make my number equals five, which we don't expect to cause any errors because the variable is a number. Actually, you see from the last video, I just left this here, and this makes no sense. This is a great demonstration of what I mentioned in the last lesson, which is that this code just skips over all of our code here and there's no reason for it to exist in the way we had left this. So I'm gonna delete that goto statement and just kinda set it aside for now. Now on our resume that there is no error here. So we skip over our message box because the error number is 0. Now we have our answer which is five plus five equals ten. And as expected, our answer is ten. And then we do section two, which is just from the last lesson. Okay, so that's great. We have our function here which seems to be the goal of adding a number together. And let's create some problems. Now. Let's create our problem right here. And from two lessons ago we have our error handler. So we should get an error over here, but instead we have this. If there's an error, just resume next. So we're just continuing forward. And then we have our if statement, which detects that an error was detected with our error object. Now we hit our message box, which has an error occurred. We can click, Okay, then things didn't come to a halt. This was a message box we purposely put up in the code still continuing to run. Now we have our answer, which is 0, because this line didn't actually set our numbers anything and it's still 0 from our original declaration. This is a great example of why you don't want to just continue running. Why you'd need to elevate errors. Because if somebody who was running this, I know this function doesn't have much of a purpose right now, but you see our answers 0. And so if we were doing something important, it could just continue on its way. Spit out an answer, in this case 0, and the user will think they receive the answer of the software once. But what we know happened is an error occurred in 0 isn't what we actually want. It's just some default that happens if things go wrong. We don't want that to happen. Instead, what we might do is if we had some important stuff going on in section two, which we don't. But let's pretend that this is some code that we want to run. We might say, go to section two. Now, we're gonna do the same thing. We have our error. We're notified that there is an error with this message box. And then we jump over the section two and we didn't prompt out and answer over here because this error we knew would cause a bad answer. So we don't want to give an answer knowing that something went wrong with this section of code. And so now we're just jumping ahead to continue in our code over here. Again, like the last lesson where I mentioned, we don't want to get crazy with this because it can get confusing. Now we have another situation where we skipped some code here. And if this was important to the code down here, then everything is getting tangled up in hard to follow again. So again, we don't want to go crazy with this, but this is just an example of what you might do. Something much more common that you'll see is maybe we'll do something like this where we say go-to error handler. And then over here at this time, you say go to our handler. And then over here, we can say if error number. Actually, before I show you this, let me, let me back up here. I'm going to lose this entire middle where we say, where we have an if statement that is checking our error number. Instead of saying resume next. Bring it back here. This resume next basically just says, even though there's an error, just go onto the next line of code. Instead of doing that, we can replace this with the go to. And just like we had the goto statement for section two, we can say go-to error handler. And what this does is if there's an error, it will just jump over to our bookmark, just like this goto statement. And so it jumps over to our bookmark here. Now, if we give it a real number on error, go to the error handler down here. There was no error. So we just continue our line of code as usual because there is no error. With this case. You can see that we don't need that statement that catches it anymore because if there's an error, we are just going to jump down to our bookmark, which is our error handling than what you typically might see. And this is really common notation. Is then down here, you can say if our number is not 0, then you're going to handle stuff here. And we'll say again error number, error description. And we'll just do a message box, although we could do anything we want down here. Now instead of section two, we've compartmentalize the end of the code being our bit of code to handle errors. And in this case we're just making a message box. So now we have an error. We jumped down to our error handler. And if the error number down here is not 0, meaning there is actually an error. Now we get our message box and we skipped our function over here. That isn't going to give us the right answer. Then if we give some inputs that make sense and we don't expect an error, you see we have this code. One thing to mention here is you can see that this code, I actually run something visibly like nothing. Notice that we happens when you run this code. It just sets the standard for what's going to happen as we continue to run the code. I'll explain that in a minute when I go back and create the error again. But you see, let me start from the beginning. We don't expect an error here. So now we run right through. We get our answer being five plus five equals ten. Now we're in our error handler section. We basically jumped down to our bookmark. But because we have this if statement, nothing went wrong, we're going to skip over this message and we don't get this message box. So now we've created some basic error handling that avoids the potential pitfalls, which is when everything goes correctly runs as usual, our error handling is down here and it does not run if there was no error. If we come over here and create an error situation. This is what I meant before, where this line of code, even though we know there's an error here, it doesn't actually do anything. It just sets the situation as if there's errors that happened below it, then it's going to use this situation. Now. It's going to jump down here and throw our error. And it did not run this code which we did not want to continue running. If an error was detected. 39. 1.24.4 On Error - Persistence and Reset: Now continuing with this setup we had in our previous lesson, let me stop here. We'll actually create a situation where there are no errors. We spit out our answer and everything works. Now after our answer over here, Let's do some other stuff. I'm just going put a comment here, do more stuff. Let's say we're doing something else that's somewhat unrelated to the code we have over here. And we say dimension, other number as long. And then we say other number equals. Steve? Now if I run this, we have, if there's an error, we're going to go to our error handler and jumped down here on this line we've been focusing on there is no error. So here we go, We're continuing. And now on this line, we jumped down. This was a bad example actually, because this was going to be the line of code. Anyways, this is going to be in the next line. Let's say debug, print out other number for whatever reason. Let's try this again. We go through all the way here and we created a situation where we expect an error to happen right here. And you see it jumps down over here to our error handler. And so what we're noticing here is that this line of code that we created in our previous examples to capture if there's an error on this line of code, this line of code was, didn't just apply to this. It's set the state of our code, meaning everything that runs after this line runs is going to perform the same function for every one of these lines of code underneath it. It's checking if there's an error, go to error handler, which is why on this line of code, this statement is still apply. And if there was hundreds of lines of code in-between, In-between here and here. Setting this state over here is still going to make it so that if you run into an error all the way down here, whether it's this line or something else, you can see there's a type mismatch. Even when you hover over the number. It still is applying this if there's an error, go through error handler. So that's an important thing to note here because I might create a situation that is trying to be more specific. So now I'm going to undo this whole go-to situation. Let's do this again just like before. And I have to remove this. Let's say section two. And we're gonna say section one. So we're going to call this section one stuff. And maybe we're doing some other somewhat unrelated stuff going on here in section two. So I might do something like this, section one error. So let's follow our logic over here. And everything crashed. I don't really know why everything crashed right here. You're going to see a quick jump to this right now, I'm going to leave in that Excel crash that you just saw, I still don't know what happened, but I'm going to leave this in so you can get the full experience of what can go wrong when you're doing development. I don't like to cut this stuff out and paint a rosy picture. So I don't know why Excel crashed in that previous video in the middle of typing, but this is a good reason to save your work frequently. I had to come back here and retype the code we had been doing up to that point. So hopefully everything looks seamless. And what we have here is where I left off before everything crashed. What I was showing you is that we can have this section one and section two, which might have some other unrelated stuff. And let's push this up slightly. It will just say other number down here. And where I was leaving off is that we might have something like this where we're saying on our resume next. And then we can say section one error occurred here as our message box. And so if I hit F8 and run through this, I'll show you what this is trying to do. We just saying on our resume next, it runs this without any issue. Debug print answer, and then we have our answer number two. Now, meanwhile, if I come over here and create this error again, create an error. We detect that the error isn't 0, so there is an issue. And we have our message box a section one error occurred. Now, if we come down here, we have this other line that's going to cause an error in our section two of code. And it's just continued on through this line. And we're deep bug printing our other number as 0, even though this line caused the problem. Again, we don't want this to happen because an error occurred right here. And we don't want the user to think that 0 is the correct number. And this issue is happening because our onResume next. Still applying to everything under here in section two is encapsulated in that this line of code is still applying to our code down here. We don't want that because we wrote this section in this manner only to catch our section one error. So there's a couple of things we can do here. We could come over here. And similarly to what we have up here, we want to say Section two. So now we still have this onResume equals an axis. We're catching our section one error. Then catching our section two error over here. So basically we're using this very common if statement checking our error number to create more specific error catching. But we haven't another situation that might come up, which is maybe I don't want error handling to happen here for whatever reason. I don't want to continue. If we have an error here, I want the normal debugger. And so what I can do is after I handle this issue, I can say on air go to 0, which basically means resumed the normal error handling that we had before. So I can remove this, meaning before we ever talk about the error handling with this onResume statement. Now, for this line of code, we continue on and we use our error handling if statement there. But now when we run this line of code, we say onError go to 0. That basically means resumed the default thing that occurs for VB editor. Which means here, now that we hit this issue, we're back to our normal VBA debugger with our Continue and in debug options over here. So this goto 0 specifically means that it means basically undo your onError statements that you may have had before and go back to default. You remember that go-to means, means to jump to our bookmark. So if we said something like Section three over here, Section Three South down here, we could also say, on your next error, go to section three. This code is pretty confusing because we're saying up here, go to section three. We're going to run into the error down here and you see it jumps to section three because everything under this umbrella is saying any issues going forward jump to section three. So this notation would be pretty confusing because this is all the way up here and it's running down here. There might be, in this case, it's really easy, but there might be hundreds of lines of code making these two things very separated, which isn't a best practice. But you can see what's going on here. And why I wanted to show you is basically this goto, which makes more sense to jump to a bookmark. But going to 0 basically just means resumed your normal thing. It doesn't say something like section or bookmark 0 doesn't exist. This basically means reset is 0. And now we are catching this error as usual here, even though we haven't error handler up here. So that's how you can reset and section off your error handler. Alright, and I'm turning on the recorder for a third time just to follow up that as I was editing that video, I realized that I think the reason for that crash in the middle is because I was in run mode. And you can see if you were one back to that section where Excel crashed up here on the top. It's at our header here. It says break in brackets. That is because we are in run mode and I was cutting and pasting and moving code all over the place while we were in run mode, while it was in the middle of thinking that it was going to run code. I think that's what caused the crash. That won't always happen, but I believe that's the reason that it just broke in the middle of typing. So you have to be careful when you are in run mode and you notice run mode when you are at the top here, I think my mouse pointer sometimes disappears, but up here there is a break in brackets. And so changing code when you're in run mode can make the system somewhat fragile. That's it. Want to make sure I tag that on here at the end. 40. 1.C.1 Automate Creating Txt Files: Okay. I wanted to put, I wanted to put together a basic series of lessons showing you some automation of our Windows file system over here, which we've already done some basic demos of creating folders, something I already did, but I backtrack here that I'll have you follow along with is I go into Google and I typed VBA create text files. And then we have this link to an official Microsoft website. Actually, we have this code that we can take here for creating a file. So I'm going to come over here, copy this code, paste this in here. And if I go ahead and run this and hit F8, I hit a compile error. It says variable not defined. That is because right away we're using these FS and a here as object variables. We know there are object variables because we're using the word set here. And of course we have create object. We just sold us from that website. So we see that they set up some stuff that isn't working for us. The reason for that is because I have Option Explicit up here as my default. If I remove Option Explicit, you can see we're good here. I'm actually going to backup. Instead of running this which would have worked, I am going to add Option Explicit plaque in which I have a past lesson, why I keep that? And we're just going to declare these objects are so dimension FS as object in a object so that they're declared and then we can use them. And you can see we're running through here. Now. I see that we're creating a file system object here. And then we're setting this a variable which isn't very the script. But maybe I'll call this as a TXT file to be more descriptive. Set a as change that to be a text file over here. And then we say we're creating a text file which were used to opening a notepad which you're probably familiar with. It's just going to put this into C drive. And I don't actually want to do that and have my C drive up here. Instead, I have this subfolder for all my lessons where I've created a folder called demo files. So here's my folder over here that I have on the left. And we have the full path over here. It looks like I wrote something incorrectly. So I'm just going to fix up my path here and I have my C drive through my tunnel of folders for Skillshare demos and then our test file here. So you see we have this create text file command, which then takes a path that includes our notepad path, test file.txt equals true. And then as we run that line of code here, you can see we have our text file. We're going to say right line, this is a test with our text file. And we're gonna do close. So now if we come back over here and see anything show up, which I expect it to. So let me come over here and do a refresh and nothing is still there. So I must have made some mistake. I come back over here and I'm checking my path. We're in Skillshare demos. And what I delete it before was just that I messed up my pattern. I must have dragged us. If you have rewind it and you'll probably see what I did wrong, but I did something and mess up my path here. So I don't have my subfolder of demo files. Now if I hit F8, right line, close, and here we are, We have our test file.txt from our full path over here. And when we double-click it, we can see it says This is a test. And that is because we wrote this line to the text file. This is a test. Now this is a bit long and hard to read, so I'm just gonna make it a little bit more efficient. So I'm going to say border path as a string. And we'll say folder path equals escape there just to exit that out for a second. And I'm going to give my full folder path here. I'm going to cut that actually. We're just going to split these things up. So there's my folder path. Let's do file name as string. We'll do it with filename equals test file that TXT. And then we'll say, actually I shouldn't have this over here and make a typo there. It will send dimension, full path as string, and we'll say full path equals our border path. And combining that with our filename here, if you want to check, we'll do a debug print here. We'll say full path just so we can see it. And then in this giant blob of text that we have above, we can type our poll. That way. We just split things up. It'll be easier to manage as we go through this. Let's try this out. I'll hit F8 folder path, filename, and then our full path is combining it both together. We have our full path over here, TXT file. We actually might have a problem here because we already have a file called that. And it didn't seem to care. So that's interesting. But if we delete this, will run this again. And here we see our test file show up. And just to show you, if I type two into our filename here, when we run this, again, here's our second test file. So here in this first video, we've just taken the code from our basic Google search from the official Microsoft documents and adapted it a bit so that we are creating a text file with some code. Now, similar to what I've showed you before that we can do with folders. Let's do something pretty simple here. Let's take our file name. I'm going to cut this and move our filename declaration down here. And the reason I'm doing that, and I'm just going to comment this out. The reason I moved this down here is so that it's separated. And I can wrap this in a loop. And I can say for I equals one to ten, indent this next pi. And since we're using I here, I have to declare it, will declare high as along. And then I'm going to take this number. And in our file name, I'm going to use our variable I here as it goes from one to ten. And now if I play this out, in fact, I'll clear this first. We'll hit play. We have path not found. That's because I move this file name down here and I didn't read declare our full path. I'm going to cut our full path here. So each time we change the file name, we need to change our full path also because it uses our filename. So I'm going to stop. We'll hit play again. And here we see one through ten automatically get created as we increment through this loop, one through ten. So that's it for this one. We'll keep building on this, on the next one. 41. 1.C.2 Automate Rename Files Fix: For this next lesson, now that we've created some files over here, some basic text files, I'm going to show you how VBA can rename a file and automate renaming a bunch of files. So what I've prepared here already is the notation for renaming a file is writing the word name, then the old file path, the word As, and then the new file path. And so just like down here, our filename is all the way on the right and a full path is our filename plus our folder path over here. I already have this pre-written to keep these videos a little quicker. But of course you could pause and view all this code line by line if you wanted to actually use it with our line of code that will change a name. You see I've already prepared our variables with this content up here. And then the actual command that will change the file name is name our variable, which is our full path current as that are full path new. Here I'm constructing it and we'll hit F8. So we step through this code. We have our main folder path, which is the one I had in our last video here that has these text files that we created. I'm taking our filename current, which is testfile one, which is this file here, filename new, which is what I want to change our file name to. I have declared these variables for clarity, where one is the full path of the current file, which is this one that exists. And then what I want it to change too, because I want to be able to use these variables in our single line command that we have over here. So now that we have our filename current and our filename new, we can create our two variables for the full path current and full path new. And then run our one line of code here. That is actually what creates the function. The reality is if you look this up, you can write the entire full path string here, and then the entire new name that you want here. And do everything I did here in a single line of code. But this is more clear and it's going to set us up for our next step that I'll show you in a minute. I'll hit F to run this. I think it takes a second to refresh and you'll see our filename here just changed. So now in addition to creating folders, the last video I showed you how you can create text files. And now you can see how we're changing filenames. And in this example, this line of code will work for any type of file. It doesn't just have to be for text files. In our last lesson where we are creating these text files. This doesn't necessarily work for more complicated files, like if you have other Excel files or Word documents. But just to show you, when I come over here, I'm just going to create a new Word document. In fact, I'll just take this entire file name here, including the DOC ex. Just remember that the file path does include our extension names here. You might not have these extension names on your computer here. The way your Windows is set up by default. I always show them. And if you come over here in your folder options, I'm just saying to select this checkmark where you're showing the file name extensions. But your file paths actually do need to include your full name and how Windows handles files and just usually hides it from you. So coming back here, you can see our current file. Let's make it this Word document that we just created and we'll do new name dot doc x here. So now as we step through again, we're doing the same thing. Current path should be the full path for our Word document we just created. And we'll change the name there. It takes a second to refresh. And you see now we have our new file name changed automatically over here for our Word document. Something else to note is that since your extension is a key part of the file and your extension in Windows tells you your file name type. If I went and did something like this, say you name one and I'll say new name to that text over here. So we're going to take this Word document and we're going to change its name. I'm going to hit play here and just run it all the way through. We've changed this file's name to new name one texts. And so we actually changed the file type here, which isn't actually what we want to do, because that could potentially make you lose data. Just for example, this text file says, this is a test. If I came over here and changed our filename, let's change it back to a Word document dot x hit F5. So we're actually keeping the same name, but I've now changed it back into a Doc X among mixed up here. But if I double-click this, you see our text is gone because as you change the file types, you can really mess things up a bit. So we'll take our doc x when we change it to an Excel file, for example, play. By changing the extension along with the filename. We're inherently changing the file type at the same time. And you see now we're even getting an error because it realizes that something has gone terribly wrong. This file isn't supposed to be an Excel file that didn't even open. That file that just popped up was actually another file that I have over here where I'm writing my code in. But it's not willing to open up this file anymore because in the background it knows that this thing isn't meant to be an Excel file. We just forced it by changing the extension on the file when we're messing around with the filename. So that's kind of a tangent on here, but just something to be aware of. The next thing I wanted to show you here is we'll do some automation. Let's clear all these files from our previous lesson. We have this subroutine we use to create all these files with a loop, one through ten. That's even beef this thing up a little bit. We'll make it 20, so it will fill up the screen and look fancy here, does macros have been disabled? So let me try re-opening this file over here really quick because I needed to click Enable content up here so I can run our macros, come back to our folder that we are working in. We're module one. So here we had our subroutine from the last lesson where we create all these text files and we changed our loop to 20. And right away Here's 20 text files that automatically got created. Now, we have our subroutine for renaming files. We're just going over, Let's do the same thing we did at the end of the last video, where we're going to cut our declaration of filenames. And we're going to move them down here. Then we use these filenames to create our full path. And that's buried in a loop where we go dimension I as a long equals I equals one to 20, indent this. Next i. So we finish our loop notation here. And instead of these names here, we can do a test file, one that TXT equals new name, one, that Px Py. And I really wanted to come back here and replace one with i variable. I'm going to copy and paste this over here so that each iteration of the loop we are going to be changing our filename. So textFile one. And then the next loop test about 2345 through 20. And we have our new name for them too. And we run this code over and over again. Where do you see as I hit F8, we have our old and new file paths here. We run this line, file not found. So let's go back here. Let's see what our current path is. If I come over here to take this variable and debug, print out our file path current. It says we don't have this file, test file one dot TXT. That's because I wrote text file when really it's test file right here. So let's drag this back up. In fact, I'll stop and start running again. Now as I hit this line, we just changed our test file one to new name one. We loop through declare on new paths, which really the only thing that's changing is one becomes a two. And there's new name two for the second file. And I'm just gonna hit F5 and run this all the way through one through 20. Since its 20th pride. Take a second for it to run. And there it is. It has renamed all of our files, all 20 files, with a click of a button. This is how you can rename a file and a use case that you might actually have is for example, you might have a giant folder full of files is, let's say our current file is called newName, which is what they actually are right now. And then for example, my new file name might be something like filename current. And I'm going to just, I'll type my initials over here, dash. So now I'm actually just using the same variable is my current filename, and my new filename is using the current file name plus something else. So you can manipulate the current filename to create your new one. So now if I hit F5 and run this off, it looks like I just have a typo over here. I hit F5 and run the cell now. And now I've appended S T to the beginning of all these files. In some situations, you might be needing to make an update to many different files. And you saw this ran really quickly for 20 and this would work if you have thousands of files in here. You can deal with it. You can do all of this with some code that isn't actually a very complicated or long hair. And then run this all with a click of a button. 42. 2.1 Moving Data - Create Form Record Macro: Since we're going to do a tutorial on moving data, I want to create a simple use case for a template on a reason that we're going to need to move data around. So what I'm going to create here is a purchase form. So I'm just going to draft up something to start with and then we're going to start to evolve it through the course of this project. So first I'm going to create a very basic form here. Will create item, quantity and price for now until we think of more things to add to it. We're going to give it the look of a form here. I'm hitting Control C to copy control V to paste. If I hold Control, you can select multiple cells at a time. Wherever you click. And then I'm going to create a border here. Now let's create a little data table for this data to go. And I like to use the default formatting out of Excel just to make this look a little better, but not have to worry too much about making selections here. And so now we have a basic user form. Let's start to fill it out. So let's say we have one pencil here. We're going to order ten pieces of them. And for a price of $1. We'll turn this into a dollar sign here. And so here now we just have the framework for the template. We're going to start out with. The first thing I wanted to do is just to show you the basics of recording a macro, which we went over in our last lesson. But we can use this Developer tab. Go to Record Macro, will click Record Macro here. We'll just leave it as the default name. And now we are recording whatever we do on the screen. So I'm going to click into the item cell, do Control C, paste control V. And I'll just do this for each of these fields. And we have moved data from our form into our table, won't even call this the purchase table. Now, if we go to stop recording, we have a macro-level coordinate background. To view the macro we just recorded. We can click this Visual Basic button. And module 1 is the default module that was created for the recording. And then here's macro one. I just show you another way you can get to this is you can click this macro buttons, which shows you all the macros that are in the Excel application that's open right now. You can run the macro or you can click Edit. And if you click Edit, it'll take you to the code here. Let's take a look at this macro that we created. Let's try running it. And so I'm just going to split these screens up so we can see them a little better. I'll just clear out this data here. Without even looking at the source code. We can go to Macros and we have macro one and let's click Run. And you can see all the data from the form went into our table over here. So let's clear this out. Now that we have our code pulled up here, you can hit F8 to step through each line of code one-by-one. And so if I'm highlighted, my cursor is in this macro. I hit F8, and then I can step through each line and we can see what's going on here. We're going to select range A5. So that's the cell address, a five over here. We're going to copy it. We're going to select I3 over here. And then we're going to paste it. And then it's just going to do that over and over again for each of the three fields. And then you can see it even recorded when I typed in the header of the table purchase table here. And so one thing is we just go through this tutorial. I'm gonna make this a little more convenient to test out. I'm going to add a button over here to our form. Well actually I'm assigning the macro here, so I'm going to assign it to macro one for now will have to change that later as we change the names of our macros, we're going to assign it to macro one. And we'll call this submit. And now if I clear the data out and hit Submit, you can see our macro runs. 43. 2.2 Moving Data - Name the Ranges: I mentioned in an earlier lesson that I don't like to use cell addresses when making macros. And by that, I mean how this macro, when we recorded it, used cell addresses like a five and C5 here, and it pastes them to i3 and J3. And the reason I don't like that is for many different reasons. But the most obvious one is if I do something like cut and paste this table somewhere else or reposition it. And then I run this macro again. You can see that it still uses these absolute cell addresses in here and nothing works anymore, or at least doesn't work correctly. We have to go into this macro and we update the cell addresses again. And the problem is then we could just move the table again and we're constantly evolving these tools as we're going. And so this requires constant maintenance and updates. So what we're gonna do here is we're going to clean this up a little bit and then change this. So we're not using the cell addresses and instead giving names to the range that will move around with these cells. And that'll make more sense as we go through this example. So one thing I'm going to do now is just remove this part where we create the table name because we accidentally record that we didn't really mean to. And so we're going to still stick with this concept for now. We're going to just keep growing on this concept and changing it to become more advanced as we go. So we have cell A5 here, and I don't want to use a five because of the problem we mentioned. Instead, I'm going to give this cell a name and you'll remember this if you watch through our earlier lessons here, I'm going to call this cell, actually I'll call it form item. And then quantity. I'll just keep the same idea. And I can just type it in this top-left address field here. And actually I want this to be formed quantity and form price. And you can confirm that this worked correctly is when you click over these fields, you can see the name of the cell doesn't say A5, C5 anymore. It gives the name the range. And I can confirm this even further by going to Formulas Name Manager, and you'll see the names I created for each of these fields. And so I can just show that this now works for our form even though we haven't handled the table yet. So if I did something like cut and paste is move these down. I'll just copy these formats to fix that. Then this original macro says A5. Actually don't want this to say A5 anymore. I want this to say form. Pencil. Again, C5 here is now foreign quantity 8, which was our price, is formed price. And so let's run this. We have an error here probably because I made a typo somewhere. Range form, pencil select. And this is called Forum item. If you're watching and following along, you may have noticed that as I was typing this and we'll run this. And you see it was able to find our source data over here in our form even though we had moved it. And you can see we can move it right back to where it was up here. It's actually one row higher. And we can run this again. And the macro confined source data because we gave it a name and this name moves around with our cut and paste. It'll also move around if we do something like insert a row, you can see the formats duplicating here. I'm just copying and pasting these generic cells to fix it. And I'm copying and pasting blank cells over here to clear those out and hit submit. And you can see it's working again. One other small thing you might notice as a side note is that the format of the source cells, because we're using a control C copy and paste when we record the macro is bringing over the formatting, which includes the borders of the cells also. And so let's do this for the table also. So we stop pasting our data up here in our original recording. This is going to be a little trickier. The more obvious thing that we could do here is to just name each of these destination cells in the table. But that's going to cause us to have a lot of names. So imagine this was a 20 column table, or the rows are going to keep going farther down as we gather data. You don't want to give names to all of those things. So I'm going to do something a little different here. Instead, I'm going to choose the top left field. Usually I choose the first column and then take the header of that as the top-left, what I call the anchor point. And I'm going to give that a name instead. So I'm going to call this table purchases. And so now this cell here is called table purchases and this is an anchor. And I can reference these other cells based on this anchor as long as this table is always moving around with this anchor cell. I'll show you what I mean here. Here where our item is going into cell I3. In this case, we really wanted to move that this part of the table and the table is down here. Now, we did create a name for our anchor cell table purchases. So instead of I3, which is where the information is ending up when we recorded our macro, we're going to choose our anchor cell, which is table purchases. And then we're going to use this offset function, which we also covered in our earlier tutorials, where I can tell you the row and column that I want to be offset by the cell. So if I say are real offset is one, that means it's this cell and then one cell down, and then our column offset, if it was one, it would be one cell to the right. But instead, we're gonna go right below it since we're working on item and our offset is select here. So our offset is our anchor cell down one row and write 0 columns. And we're going to select that. And just like our recording, we'll leave this for now where we paste or item. And then for quantity, our selection instead of J3 will replace this. And you can probably see where we're going with this. Our column is just going to be over one to the right. So add one there. And then k3, which is up here. We want to move that down to this cell. And again, we're going to use the anchor. So we're just gonna go over to the right two columns and down one row instead. Now we have the selection of i1. That's just when we created the table heading. And so we don't need that anymore. We're just going to delete this here. And so if we did this correctly, what we should do is take the values from each of these three cells and then paste them in each of these cells based on the anchor of the table. So let's run this. And so you see that worked. Let's try this again. So I'm going to cut and paste and move this table even farther down here, you can see our anchor cell moves with it, table purchases. And so I can clear this again now and try this again. And our data continues to move with our named ranges. And then I'm just gonna go ahead and clear this out. 44. 2.3 Moving Data - Simplify Recorded Code: Now that we've updated our tool, so we have named ranges and we can move our data around and feel confident that the logic is still going to work out. What I wanna do is just clean up the basic functionality here. When we record macros, it's a bit inefficient because it recorded every action that we do. But since we're working with the source code directly, we can actually cut out some of the steps that we do when we're manually working with Excel. And so for example, when we're selecting the form item cell, which is over here and then copying it. You can see we're first selecting it and then I hit Control C and do the copy of the selection. I can actually cut this out and make these into one where I don't have to click into the cell since I can refer to the form item cell, I can just copy it directly in one line without selecting it and then saying, I want to copy whatever I have selected. And so we can cut these out. And the same thing happens for our destination, where we're going to select this cell, which is what this line says. And then in our active sheet we're going to paste in whatever So we have selected. I should be able to actually come in here and just type paste. I'm not sure if pace is actually going to work the same. So I'm just going to comment this out and check if this update works for this one item field. Let's clear this out and then we'll hit submit. And you can see paced actually did not work quite as well. Now that we've realized that for now, I'm just going to hit Undo and then leave the pasting here for now we're going to come back to this. I'd like to leave in these little tests that I'm doing in the tutorial. So you get to see the full process here. For the copy. We saw that that work and it only had a problem with the pasting. So let's run this again just to see if that fixed it. So you see this reference where we chose the form item directly ended a copy that work and we cut out some of the inefficiencies of selecting the cell first. So let's do the same thing here. So form quantity. We'll come over here. Instead of selecting it, would just say dot copy. And then we can delete this over here for the form price, we can remove the select with just the range and copy. We're just going to leave this in here. I'm not sure if we need this right now, we'll test that out. But this is the equivalent of hitting Escape when you hit copy. So you see how we have the moving dotted lines here. This is hitting Escape. So that's what got recorded here automatically when we're recording our macro. So let's try this out. Now you see we have an error here and it's saying we have an error when we're trying to pace. I'm realizing the reason for that is because we don't have anything in our copy clipboard right now. If you went back and looked at how we rearrange these lines of code when I made it more efficient, is the copy line was actually here. This is where the old copy line was with selection, that copy. And we move this and you see because this one, sorry, I didn't like that. This isn't a valid line of code here because this line is the equivalent to hitting Escape. That was similar to clicking this field hitting Control Copy, hitting Escape, and then trying to paste in here because it had escaped with this line of code, then there's nothing in the clipboard. And so what I really need to do is let's see if we even need this. So let's try this out. We can run this step-by-step so we can see what's going on here. You see we're copying or pasting copying here we see the dotted line and we hit the active sheet and we paste. We're going to hit the same problem here and you'll see what I mean. Here we have the price and the clipboard. And then when we run this line, it deselects the copy from the clipboard. And so we're going to run into an error right there, right here actually when we try to paste. And so we'll go back here. You can actually drag this arrow up to go back to where we were before. Now we have price in the clipboard again. And I think we can actually remove this because we inherently unselect our copy when we copy something else. So you don't have to do the equivalent of hitting Escape to take something out of your clipboard. We can just skip that line completely. And then we have something working here. What we're actually seeing is because we don't have that line of code that deselects our clipboard. You can see this is still active even though our macros completely finished. So if I hit undo here, we'll clean this up. We'll actually just move this till the end. And now we'll run this step-by-step just so you can actually follow along now that we're editing code manually. Now rather than just using the pre-recorded macros, you can see this custom code that we created, how it runs step-by-step. And so now I'll hit F8. We step through it, we copy item, we paste it into our cell, and we do the same thing for three fields. And then now that we're done, we hit Escape to clear out our clipboard. 45. 2.4 Moving Data - Paste Values Only: Another small thing I want to go over is just because we're using a copy and paste here. You saw before that we're moving the borders over to our fields here. And that doesn't really matter to us because it looks okay in this format, but it's not always something we want. In fact, very often you're only going to want the values and not all the formatting of the source fields. So what we wanna do is do the equivalent of pasting just the values. Just to show you what could go wrong here, I'm just going to clear these cells out, including the formatting and show you that if I did something like have this cell is highlighted. When we run this macro, the entire formatting of the cell moves over here because it's the equivalent of doing a copy and paste. So I'm going to clear this out. Let's clear these again. I'll bring this back to white. What I wanna do now is basically just make this the equivalent of a copy. And then paste right-click and then paste special. There's these shortcuts here. If you've got to pay special, you'll see it actually written out and paste values. If this was highlighted. You'll see that if we did this and went to paste special and values, that only the value and not the formatting of the cell moves over. And that way we can control the formatting of this table without getting overwritten by the formatting of our source data. How are we going to do that is updating these lines of code for pasting into what is the equivalent of a pays value, rather just a typical copy and paste. I don't actually have that notation memorized. So like in my earlier tutorials, I don't want to just look that up and have a notepad over here and type it in. Instead, I want to show you the process that you can use to find information if you don't know it. And I don't show it in these tutorials. So what I'm going to do is just go over here to Google and I'm going to type VBA, paste special values only. And so if I go over here, you can find notation and these websites, I'm just browsing quickly to our answer. You can see you can take a range and then it says Paste Special and then Paste Values. And this seems to be a property of a range. So let's try this code out. This is our range over here. We have an offset on that range, but this is still considered a range. So we're going to remove this select and do a paste specials. We have an extra period here. And then with this, we could actually comment out this line because I don't think we need it anymore. So let's try this out. In fact, I'll paste it in here because that's where we have our highlighted quantity cell. And let's just try this out. I'll clear this, It's submit. And there you go. You see we paste values in here and the formatting of the highlighted cell did not get moved over. And I'll do this for the last cell here, just for the price. Actually don't have this in my clipboard anymore, so I'll copy from this other line above it. And then we can just clear these lines out. And here now you see as we're doing manual updates, our code is getting more and more efficient, which is best practice that we want to do. When we recorded the macro. It had a lot of extra steps. The more we can simplify the code itself, the easier it's going to be to maintain our code in the future. So we'll test this out one more time now that we have all our updates, you see the self self-appraisal price still has our formatting here. So I'll clear that out completely. What submit. And now we have just the values being moved in here. Price, we still want to be in dollar notation so we can make this field itself and accounting field. And it's going to maintain that formatting in the future as we add different values to it. So even if we change this to a dollar 50, we can hit Submit and you'll see it updates in it retains its accounting cell type. 46. 2.5 Moving Data - Without Copy and Paste: Up until now, what we've been doing is starting with our baseline where we recorded a macro and did a copy and paste into these cells. Even this is slightly inefficient. We're recording macros, basically we're doing it the way a regular user or person sitting in front of their computer would move data around. Because we have access to the code directly in VBA. We actually don't have to run things the way humans sitting in front of the computer clicking with the mouse and keyboard would run things. So in this example, I'll show you what I mean by that. So our process here is basically copying each field in our form and then pasting it to our table. We don't actually need to do that. We don't need to do a copy and paste. And then what we've done before with a paste specials to retain our formatting. Instead, because we have access to these variables directly. We have this field over here being table purchases with the offset. Because we have this reference of this field, we can actually forget the copy and paste. This cell has a property called value, and we can just set this equal to something. And so if I set this equal to Steve here, we'll run this now. And you can see we just place the, this line of code, just place the IV directly into the cell. And I have my source data here, which is what we did a Control C copy from. We don't have to do a copy. Instead, I'll just take this source cell, which is over here. And instead of the text that I just typed right here, I'll put the value of that. And so basically what this line of code is saying, and we don't need this anymore, is that this cell over here, which is referenced to the left side of this line of code, will equal the value of this cell over here. And so this is basically the equivalent of a copy and paste only. It'll be even more efficient. So let's try to run this and you can see that the macro still works the same and the item pencil has moved over to our table. So let's do this for the rest of the code. We don't need this line anymore. Value equals the value of our source. And we can do the same thing over here. We'll cut value equals form price stop value. And this where we clear the Copy clipboard doesn't matter anymore either. And you can see we're getting much more efficient here. So you can see where the shortcomings are of recording a macro and how much more efficient working with the code directly if you know what you're doing can be. So let's show this whole thing. We'll clear this out. Hit submit. And here we have the same result as before, and now we're only down to three lines of code. And you can see the same thing still applies. The highlighted cell, the formatting did not move of this table. We're just moving the data we want. And one thing that this simple example isn't showing is as your macros get much longer, they can become pages and hundreds and thousands of lines of code. This is much more efficient. And so this could be the difference between your macro running for thirty-seconds or even multiple minutes. Or it running much more efficiently and being done within a split second or a matter of seconds. 47. 2.6 Moving Data - Writing to Next Row: Now we've created a very clean macro here with just three lines of code that moves three pieces of data into this table. Next problem that you might be thinking of already is that our macro just keeps moving information from this form into the exact same fields over and over again. So to make this an actual transfer of data into a table, we're going to want to append a new row every single time we hit Submit so that we get another row of data each time we submit a new line item here through our form. There's many different ways to do this. So I'm just going to show you one way that you can do this for now. The first thing I wanna do is figure out what my next line is. And because this might fill up with data over here. And we might have more lines, we need to go through this table and figure out where our next row is going to be. How I'm going to do this is I'm going to use this anchor table. And in our earlier lessons, we went through loops. So that's what we're going to utilize to figure that out. I'm going to figure out what our next row is before we even do anything. So I'm going to start to draft up some code before these lines where we're adding our three fields at a table. One thing I'm going to utilize here is this named range, which is our anchor for the table over here. What I'm going to do is start at this cell and then work my way down this table. I'm going to do a for-loop, which we went over before. I'm going to start with just some numbers I'm going to make up here. I is 1, 2, I'm just going to say 99 thousand, just a gigantic number that I don't think our table will reach, at least not in the foreseeable future of this demo. So I'm going to say next, I, this is our notation for our for-loop. And then I'm going to choose this range or anchor for the table purchases. And I'm going to say offset i 0, that value. And so I haven't actually finished this line of code yet. I just want to show you that what I'm referencing is only our first loop, I is going to equal one. And so just like we used over here, if offset is one, that means one row down from this cell and 0 columns to the right. So we're talking about this cell over here. And then the next time this loop goes, I is going to become two. And then we're going to be talking about this cell here. And you're probably starting to get an idea of what I'm gonna do. So I'm going to wrap this in an if statement. I'm going to say if offset 1 equals blank, then I'm going to end this if statement here. But basically I'm going to put some code in here that says at end of table. And so when I equals one, there's going to be something here. And so we're not going to meet this if statement. We're just going to move on to our next loop. So we're going to skip out of this if statement. And we're gonna go to the next loop. When I equals two, we're going to be over here and then the value will be blank. And then we're going to end up inside this if statement. And then this next blank is going to be our first row. We're going to create a new variable here, and we'll call it DEM. Next index as integer. And so when I shows us an index that brings us to a blank row, we're going to say next index equals i. Now we don't need to keep running this loop because we've already hit the bottom and we don't need to run this loop 99 thousand more times. So we're just going to exit the for statement right here. Now when we're done this for loop on next index is going to be two in this case, which is really the location of our next row. And so where are we? We're always adding data at just one row down from our anchor point. We're going to use this variable next index for how many rows down from our anchor, we want to go and add the next data. And so if we change this here, now, we're just one row down, we're going to be a two when we run this. At least that's what I expect. And then we're going to be setting these values to these form values again, because it's hard to see everything. I'm just going to shrink this down a little bit. Because we create these named ranges. I can do what I just did and everything's working correctly. And so you can see this is one of the key benefits to working with these named ranges. Because it's the first time we're going to run it. I'm actually going to use F8 and step through this code and hopefully the concept works just as I described it. And so we're going through the loop here. I equals 1. We can highlight over these variables just to see their value. The value of one row down from the anchor is not blank. So you see we jumped out of this if statement. We did not enter into it. And then we're gonna go through the next loop where I equals 2. We're talking about this cell here, and the value is blank and silver in next index equals two. We leave the for loop. And now our next index is two. And now we're going to set the value of our anchored down to rows. And it looks like it worked great. Just to prove it. We're going to change this up a little bit. I know these example prices might not make any sense. So bear with me if you're thinking to yourself that this isn't what a pencil costs. Hit submit. And you see are updated. Macro works great and we can keep adding information to this table here. 48. 2.7 Moving Data - Add Timestamp: There's one feature that I want to add, this tool that we're creating, just because it's a very basic feature that would typically be part of a form to database tool like this. And that is a timestamp on when we are adding this information. And we have this functionality we built up already where we can keep adding lines in this table. And I want to stamp each record with the time that we added this row to the table. That information isn't in the purchase form and we don't want to ask a user to type in the date and time every single time they are submitting a new line. We don't want them to do that themselves. And so we'll just do this right in the code over here. We can use the same concept that we have over here, where we have our anchor. We have our index for how many rows to go down to find our next row. But our column is now our third column over from our index. So 123 is our timestamp. And instead of taking the value of a named range from our form, which we already have over here. We can just use a VBA function and we'll use the function now, which is a timestamp. And so let's add a row here. You'll see we have a timestamp value that's now shown up. We'll make this a little bit bigger just so we can view it. Actually, we can make this quantity much smaller also to give us some room here. And you can see as we are adding these rows, we now have a timestamp in here also. 49. 2.8 Moving Data - Writing to Different Sheet: Next thing I wanna do is split this information up. And that's gonna give us a chance to see how we can move data between two different sheets. So I'm going to create a new sheet here because very often we wouldn't have a user-friendly form like this right next to the data table itself. So instead, these might be in two different locations. So I'm going to cut and paste our table, and I'm going to paste it over here into another sheet. You can see because I use Control X for cut and paste, our named range actually moves with it. And so you see over here, where would have been our anchor cell? That name moved with it over here to this new sheet that we created on that alone. Let's see if this works. So I'm going to change the quantity here. I'll change this to paperclip. I hit Submit. So you can see here that we didn't need to do anything because we had named our ranges and table purchases moved over here. This sheet actually knew the table purchases was on a different sheet and was able to find it even though we had moved it. One thing we can do here is we're going to write form. And over here we'll call it table data. And we can keep adding information over this table and you can see it continues to work and we have our new timestamps. And even though this work, I just want to show you that it's always better to be more explicit in how you're writing your code. Just because in different situations we just haven't hit it yet. But this code could get confused because we have two different sheets and it might not know what information we're trying to reference. This isn't a problem yet, but something to be more explicit could be adding a sheep call out. And we'll say from table data, range table purchases. So now we're telling R code that the range table purchases is very specifically in the sheets called table data. And we could do this for all the rest of them. I'm not gonna do it right now, but this would be more explicit. So you're telling the code exactly what's going on. And we can try this again just to make sure that it's still working. So you see in this case, this information right here, it wasn't needed, but adding it doesn't hurt. So in different situations, this may work better and even be needed for everything to work correctly. While we're on that topic, I actually want to just come up with an example to show you when the Shi call-outs need to be specified. The way I'm going to do that is to take this data right here. I'm going to clear this out. I'm going to comment out this line. And instead of writing our item, we're going to fix this all back later. But just as this demo, instead of writing our item over to the next row of our item column, I'm just going to put this in cell A1. And you're going to see that we're writing a one. And we ended up changing our purchasing form over here to say paperclip, because this form does not know that A1 means table data. In fact, I didn't even bring that up when I change this code. And so you can see A1 is on different worksheets. And if I make a new worksheet and I want to write to a one on sheet 1. I'm going to have to specify directly. And so I'm going to change this back to purchase form just to fix the mistake we made over here. And then if I want to write two sheets called Sheet 3, that range A1, that's what I need to call out specifically in order to move that data over here to sheet 3. 50. 2.9 Moving Data - Tidy Up: Hi everyone. So I realized that it's been a long time since I posted my last video over six months ago and never follow up again. So I want to pick up where I left off and just continue the Excel automation lessons. So we'll dive right into it hopefully seamlessly from where the last video left off. For this video, what I wanna do is just clean up what we created before. So where we left off is when I click the Submit button, we should be adding a new line over to this page over here. And you see the new date compared to where I last left off. Let's change one of the values here. Just make sure everything's working correctly and hit Submit. We're going to come back to this. One thing is after I click the Submit button, I don't know if anything successfully happened. So I'm gonna come over here and see that our new line that we added is showing up successfully with now the new price of $15.1 thing I didn't like about that was that when I click this button, I could not tell if anything happened. So let's change this again. Hit submit and you see we just don't know that anything successfully happened. So let's add a simple function to give a pop-up message to indicate to us the user or anybody else who's using this that the code successfully executed. So we're gonna go over here, back to our module. We left it as macro one here. So we'll come back and fix that also. So just as a bit of user feedback, we're going to just say line has been. So let's go back. We'll run this again. And we see line has been added. Now we actually know that something happened and we got a bit of feedback from program. Now as we come back to our code, we can take a look here and see that it says that our subroutine name is still called macro one. So that's not a very descriptive name here. Let's change that into something more official here. So we're going to say add lime from now because we changed that subroutine name. When we go to click this button, we see that we cannot find macro one. And that's because this button is still attached to a macro named macro one which doesn't exist anymore. We change that name. So let's reassign this to the one macro. This is nice and easy to find because there's only one so far. To add line from form. Now when we click this, the same routine runs. We continue to have our lines add up here. I'm just going to clean this table out. Just so it doesn't grow so tall right now that we have to scroll to see it. As we add another line, we see our subroutines still works. Now that we have this data table on the other tab, we don't need this one anymore. So this was from our earlier lessons. We can go ahead and clear this out. And one sheet that I like to use to clear out content is if I highlight here and hit Delete, you see all this content still stays here. All this formatting is still here. I'm going to undo it just so you see that I can do from here is I just grab a blank cell, completely, copy it, and paste it over here I was doing control C and then highlight and control V. And I hit Escape to stop the copy and paste mode. And now all of this has returned to normal blank cells. And that's because I copied a normal starting blank cell and pasted it over top of the stuff I wanted to clear. There's other ways to do it, but that's just a really quick and easy way. I usually do that. Now I'm just gonna go ahead and clean this up a little bit. I don't really like the way this looks. So let's change the appearance of this form. One thing I'd like to do for forms is to get rid of these grid lines. You see the spreadsheet has these lines here, which is normal to all spreadsheets. But we want this to look more like a form and less like a spreadsheet. And this is just for visual appearances. I'm just going to remove gridlines and you can see all those lines go away. And this looks a little bit more like a forum. Now I'm just going to clean things up and make this look a little bit better. I'm going to move the button out of the way for now. Let's change this font. Let's put this back to normal and we're just going to make this bold for now. We have this gray background that I set up before and I'm just going to undo that, say no fill. So we're back to the default here. Let's rearrange this also. We have this random form setup. Instead, let's start to align these things up vertically. What I mean by that is I can take quantity, I'm gonna do cut and paste or Control X. I'm going to paste quantity over here and price. And I want the labels for the fields to be over in this first column. And then in the second column, I'm going to put the actual field. You see, we had named this earlier as the Forum item. From our earlier lessons. You know that if I do a cut and paste, this name will travel with the cell. So if I do a cut and paste, you see, even though I move this from here to here, the name form item has still traveled with this cell. I can do the same thing for these other ones. I'm doing a Control X, Control V for cut and paste. I have these setup like this. Now, I'm going to right-click and delete these. And let's just make this stand out a bit more. I'm gonna make this black here. It will make the font white. Move this back over here. I'm just going to put some Colin's here. Now we have a much simpler, I think, cleaner looking for that we're just starting with and we can continue to add information here as we go. And then before we move on to the next video, we'll just test this out and see if it still works. So let's change these numbers a bit. Call it a binder. You click it, line has been added and let's make sure that they made it over here to this other page. And you see, here's the new line, we just add it. 51. 2.10 Moving Data - Validation Before Process: In the last video, we just cleaned up our user interface a bit and added some very basic functions to catch up on this project. Now, we have this submit button still works. It gives us some feedback messages there. We've added this line. Now I want to add a little bit of validation to make sure that the user is using this form correctly. For example, if I did something like delete the item from this field here from Forum item and hit submit. Our process still runs over here. You see it added this line, but we don't have anything listed as the item. In a lot of cases, we don't want the user to make this mistake. We don't want this action happen. We want to tell the user that something's wrong before they submit it to the table. And then they can fix it so they can submit it again. Let's go back to our code over here. Go back to our module. We have our add line to form. This. What we wrote already is what adds the information to the data table on the other tab where we want to put our validation is at the top of this subroutine. So that we checked to make sure certain conditions are met. Before we run this process of actually adding the line. I'll put a comment here. I'm gonna just say add to the table. And then I'm going to prepare up here, which is where we're going to add more code. And I'm just going to call it validation. This is where we're going to validate the process. In this exact scenario that we just tested. What I wanna do is make sure that there is something entered in this form item field. Over here. We see that the form item is called out here to be placed into the data table. One thing we can do is take the same call-out over here, which is where we are getting the value of this range, one item. We're gonna put that in an if statement. So we're going to say if the range Forum item that value equals and then just two quotation marks blank. Then we're going to perform whatever happens inside this if statement. So basically we're going to add a message box here to say that item field is blank. So let's test this thing out. Before we do that. You might notice that if we enter this if statement, meaning form item is blank, we're gonna come over here, we're going to pop up message box. But then after that message box pops up, it's going to continue on its way down the rest of the code over here. So to stop that, if this condition is met, which is that the Forum item is blank, we're also going to end the entire macro. So we're just going to cut off the macro here. Another way we could write this is Exit Sub. Instead of doing an end here, which would exit this subroutine, we won't get into the reasons why I'm going to use end here. But exit subroutine could possibly just leave this subroutine that we've written and continue through another one if you have a bunch in the process. And it's just going to stop this entire macro cold wherever it's at. Let's try this out. Item is still blank. We're going hit Submit. It says item field is blank. And so let's change our number over here. You'll notice it did not say it was successfully added. Item field is blank and it doesn't give us the message that shows that the process has been completed. So if we go over here, we see that our line has not been added. But if we go over here, we add an item so that it isn't blank, we can continue this process. Now that we see that that works, we can come over here and let's add the rest of our validation. I'm going to just split these windows up over here so we can see what we're doing. And let's think about how we can make this validation a little easier, because we want to check for all three of these fields. So something you might be thinking already is to do something like this form item. And then here's our form quantity. Then now we're calling this cell over here and seeing if it's blank and we're just doing the same thing for this other field. We can call this quantity field is blank. And you can imagine if we leave quantity field is going to skip over this one. I'm going to hit F8 to step through this code here, you'll see that it checks whether Forum item is blank, which it isn't. So it skips over this statement. It comes over here, form quantity is blank and so it gives us the message box now. And then when we hit this, it ends and the macro stops. And we never want, you might notice, is if we follow this pattern, we're gonna put formed price over here. We could say something like price field is blank. However, if we run this again, we're going to hit forum quantity. Get this message box, and then we just end. If we have a situation like this where quantity and price is blank, then as you step through this code, we're going to get our message box and the macro right here, and we're not getting our error message, that price is blank and that needs to be filled in also. That's not really a big deal here, but as things get more complicated, you might want a better system than this that ends up having a decent amount of code. So we're going to write it in a way that's shorter, but also we'll run through all the validation so it can show you all at once, rather than just stopping partway through like we do in this method. So I'm going to show you a really common way that I like to do this. And I use this same setup all the time. I'm going to make a new variable. I'm going to call an error message. And that is a string, so it's basically a text. Then with this exact situation, if the item is blank, I'm not going to put a message box and just end the macro right here. Instead, I'm going to say something like error message equals item is, item, field is blank. So let's see what happens if I do something like this. Now, when we have our blank item over here, we have very little info here. Now we have no info really. If I step through this code, you'll see we see that item is blank. We add this text to the variable error message, and then we don't do anything, we don't stop, and this will continue forward. Now this is just our old process here. And so the question is, when we run through here, since we're not stopping the macro, what's going to keep us from running this ad line process. And how I'm gonna do that is right underneath here. We're just going to set this aside for now. We're not going to worry about this. We are going to say, IF error message is not blank, if we're running this validation to make sure that this field is filled out and otherwise we're going to stop everything. This condition will put text into the error message variable. And then at the bottom here, underneath that, if there's anything for an error message, then that means we need to stop. We're going to say issues. And then I'm going to append. We've got purposely make a mistake here, but I'll just put this here. And I say issues the template colon space. And then we're going to add the error message. And then we're gonna do an end here. So let's run this. I'm going to continue to run this line by line. So we hit F8, you see items blank. We populate the error message variable with a message. And then over here, we see that error message has some content. This symbol does not equal blank. The error message isn't blank, which means we do have issues. The issues detected. We get our pop-up issues detected. Item field is blank, then we end. Now if you play this out, I won't actually do it right now. But if there was actually something in form item, then it will skip over this if statement. And then by the time you get here, error message is blank because we never called it anything. We could actually be more clear up here by just saying error message starts off as blank before. Does this if statement. But when you declare, it starts off his blank anyway, so it was implied that it starts off as blank. And then when we get here, it will just skip over and then continue down and run our processes. For just one validation. It doesn't matter too much. But now let's solve the problem that we had before, which is that with three different scenarios, three fields we're checking for. We would stop at the first one that it hits and then not check the rest of the messages. So instead, let's come up here and we're going to move this statement up here. We're going to say if quantity equals blank. Then we're gonna do error message equals quantity field. Right? So I'm going to purposely show you what's wrong with what I did. So we're going to work our way through this. I'm just gonna go ahead and delete these two that we had before. And so here's our new stuff. We have our error message, and here's the first situation we check for, which is item and here's the second which is quantity. And then we check for whether or not any of those conditions were met. So if I walk through here, you're gonna see error message equals. We meet our second condition, which is the quantity is blank. Now we have an error message. So we show our message which has quantity field is blank. And we'll end it and then the process stops. Our problem here is that our first message was overwritten by our second message. So in order to make our first message persist, we need to say that error message here equals error message. And the second message over here. So let's just see how this looks. Here's our first error message. Id field is blank. Now we're going to say item field is blank. And the new message combined becomes our error message. So as we go through this, we hit our message. You see item field is blank and we appended on top of that because we said equals error message plus something else. So it's adding to itself that quantity field is blank. And then we end our process. And you'll notice the formatting did not look very good. So something we can do here that add in-between is a VB LLF, which is visual basic line feed, which basically means starting a new line. So I'm gonna say, and here. And we'll see our new message as we run through this. As I step through this, We get that message. Now, this just creates a new line. And here's our new format. It pushed the next bullet to a new line. Let's keep out the details I think you could follow what I'm gonna do here. I'm going to put a line break in-between the issues detected and the bullets. So actually I'll just go ahead and run this. Now used to seeing it's starting to look like this where there's a new line in-between issues detected in our bullets. One thing I can do is instead of putting it here, I can just put those new line behind each of the bullets here. If I run this, you can see there's an extra blank line, but it's not something you really notice. So it's just an easy thing to put this at the end of every bullet point so that the next bullet point will start on a new line. Something I like to do is to just place this over here. So this has error message equals error message and appending, even though in this case it's always going to be blank by the time you get here. It's just an easy practice to always be appending new bullet points to the message. So I do this even though we know that this is going to be blank in any situation where this line of code runs. Because now if I wanted to, for whatever reason, I can do a cut and paste and swap the sequence of these. And when I hit Run, I was hitting F5 for r1 here. Both of them still work with the same formatting. Only we're checking the quantity field. Before we're checking the item field. I'm just going to move this back so that the messages are the same order as shown on the form. And then our last one over here, I'm going to do a copy. Paste. In our last field was formed price. So let's just watch how this works. As I hit Submit. We're entering each of these statements and appending a bullet point to the message, and we have a new line to make the formatting look nice. So now we have issues detected and listing each field that is blank, that's preventing us from moving forward. If we want it to be even more clear, we can say something like issues detected, process, canceled. So let's try this out. We hit Submit, we have all three fields are blank here. We can try different sequences. We can say item, paperclip. Now, only quantity and price field are blank. If we enter the price, $50, I know this paperclip is getting more and more expensive. The only field is blank is quantity. And we'll enter our quantity of a 100. And the line has been added, which is that we passed all the validation and the process that the buttons attached to officially completed. And here's our $50 paperclip. 52. 2.11 Named Table Object (List Object): For this next video, I wanted to jump to a different topic, which is a different way to work with table data than most of us are used to when we first start off with Excel, we've been working with this data table here. And this is just in the format of a table. And this is how we very often use spreadsheets, is we just kinda start on the top-left and we start to make tables of information as we type into the cells. Something that not that many people use, especially when they're starting with Excel, is the fact that Excel can make table objects. So similar to how there are worksheets and cells. And that is the base thing that we're all familiar with in Excel. You can turn this range right here into an official data table. And you might be asking yourself, what does that mean? Because this already looks like a data table. But if I come over here and I say Format as Table, I can choose a couple of different formats here. A really common one is this one. I'm going to select this. And you see it asked me, what's the range of my table already automatically filled out what I have selected. I could change this range by selecting other things here. But because this was already selected when I chose this Format as Table button, that it already has my range selected, I'm gonna hit Enter. I'm going to say my table has headers, which means in this range that I select it, I have headers, which we do here that we already made blue. And I'm going to click Okay. And what you may have noticed if you rewind ten seconds to before I ran that, is that when I'm clicked in this table now, this has Table Design up here. And that's because this is a fish or a table object. Similar to how we named cells over here, where our item isn't a cell range and we named it Forum item. This table is now this range over here. If we click Table Design, we can see the information about this table object. And we have a table name. This is called Table one. Right now. We can even do something like change our table name and we're going to call it table purchases. You see it popped up that message saying that I cannot name that table. Table purchases. That is because we have this one cell up here, that is the anchor. And we named our cell table purchases and it's not letting me reuse that same name instead of have to come up with something different. So I'm just going to call this table purchase lines. And I hit Enter. And then now when I click out, we don't see our table ribbon up here. When I come back over here, we are in our table design. So this is all the properties of the table. I can change my themes here. You see how this is still blue. That's because we manually set this to blue a few videos ago. If we come over here and change ourselves style back to normal. Normal isn't actually a cell style. You may think that it means there's a white background, but it really just means to leave it to whatever Excel's default is. Because this is a table. It's going to take the style of however we style the table over here. So now we can see even the header because we did not specify a specific background color. It's just going to accept whatever formatting we choose from our table style. We're going to use this in our automation and our VBA code. Even before we get into that in our next video, you can see that there's some benefits to this being an official table and that it is a known object with a bunch of settings that we won't get into all the details on here. But for justice starters, you can see how we can format everything. You may have noticed how there's automatically these sorting functions at the top of each column that often you'd have to manually add. And then one really cool thing that you would see here is that if I manually add information to the table, even if we're not using any macros or VBA for automation, you can start to add lines here and you see it automatically new to extend this table as I add it, question here. This table has a lot of logic and intelligence built into it. Now that Excel knows that this is an official table, rather than just a bunch of content in random cells throughout the spreadsheet. And then I can even come in here and do something like Delete. And now I have, when I right-click, I have these new options, Delete columns or delete a row. So we're going to leverage this table object now that Excel knows that this is an actual table. 53. 2.11.1 ListObjects (Table) - VBA Intro: In the last lesson, I introduced you to this idea of a name table which we have here, which we've converted our data into an actual name table. In Excel recognizes this. There's a lot more information we could go over on name tables just here in Excel without getting into the VBA. But we'll save that for another time right now, let's dive into how to work with this for VBA Macros and see what some of the benefits are of having an actual name table rather than working with all the raw data in the spreadsheet cells. Let's dive into the VBA code here. I'm going to open up our editor. We just have this on both sides here. And let's just make a module. So I'm going to kind of set aside the project that we've been working on and instead, just have this lesson on the different things you can do. Now that we have a name table here on the spreadsheet. So let's create a new module. I'm going to do right-click Insert Module. And I'm just going to call this name able. So I'm going to call it testing. We're just going to use this to execute random code to demonstrate some of the things you can do with this name table. In VBA. These name tables are actually called list objects. So first I'm going to declare a TBL. There's a table variable as, and we're going to call it a list object. So you have these options here. I'm going to choose list object. And then I need to set this variable to be the table that we see here on the screen, which you remember from the last video. I'll expand this so we can see the name here. We call it table purchase lines. So we're going to remember that name here. So we're going to say set PBL equals. And then we're going to call our sheets able data. And that's the name of the sheet right here. So we have to tell it the name of the worksheet that the tables in that list objects, table purchase lines. So we're calling this a lot like we usually do a range, but instead of a range, which is one or many cells were saying a list object, which is the tables on here. So if there was more than one table on the sheet, there'll be multiple list objects on this worksheet. So we're telling it of all the tables on this sheet. We're going to choose the table purchase lines object. Doesn't matter right now because there's only one. But if there was more than one table, it is telling it which table to declare for our variable. So now something simple I would like to do is just say table. And you have all these properties of the table object, of the list object. I apologize, I'll probably be using these words interchangeably, table object and list object. Save range, which again we know is a group of cells. I'm just going to say select. So let's walk through this F8 to step through the code. Here. Tables nothing. Now the table becomes table purchase lines, which is this object right here. And then the range is the cells in this table. And when I click Select, you'll see it knows that here is our table. One of the benefits you might see right away just from this example is that a lot of times you have data anywhere on a spreadsheet. These spreadsheets are gigantic. They can be hundreds and thousands of rows and however many columns over. And you see in this case, the data isn't perfectly to the top left or anything like that, which some spreadsheets are. But your data can be floating in the spreadsheet. And so right here, you can see we already this benefit where when we're declaring this name table object, we know exactly where our data is. Now that we have a table object, this list object has a bunch of properties that are part of it. It has tons of properties. There's no way we could go over at all, especially in one lesson here. But I just want to show you some of the very basic properties of this table we now have access to really easily. So I'm going to say table. And then you can see all the options here. I'm going to say Data body range. So this is a range. And then you see it has select just like our range has, select this as the date of body range. Now, if I step through, we selected the range and here's the data body range. And you see all did is basically remove the headers because this is our data in any table. And right now we have a very small data table, but this could be thousands of rows down and dozens of columns to the right. And it would know your body is basically your table minus the headers. And we can add more things here. We're going to do. Let me back up here. We can do hetero rings that select. I'm going to drag this yellow arrow up just so we can run this line of code. And you see it knows the header row range. The top over here. So now you're starting to see some of the things we did in the past videos where we have an anchor cell on the top left. And we're doing things like trying to find the next row. We have access to the properties of the table and we don't have to do as much work to find out information like where is the top row and where is the bottom row of this table? Tables have a bunch of rows to them. And a lot of times when we're working with data tables, we know that we're trying to go through the different rows of information whenever we're working with data, that's a really common theme is that you're trying to either find a specific row or loop through all the rows of information. Tables. Have these lists row objects, which is each row of data in the table. And so same thing here. See I have lists rows here. I actually have to backup and if I started parentheses, it'll give me an index. So if I say my index is two, my list row has a range property and I can do select it again. We'll move this arrow out one. You see I'm selecting the second row of my table. And of course if I change this to five, again, we jump over to the fifth row. And then if I go outside of the range, you may expect this already. We're going to throw an error here and it says subscript out of range because rho tenth doesn't exist with our list row. Let's go back to three here. You can see as I back up to our list object and just put the period, we have these different things we can do. The range is what we're familiar with, which is interacting with the cells of the row. But then you have these other things, like we have delete right here. Let's try this out. If we run this line of code which has lists, row three beliefs, you can imagine what will happen next. So if I run this, row three is now deleted. And now you're starting to see that we have a lot of control here. Things that we were doing in the past, like even before using the variable I to index how far we are from the top-left. We're doing a lot of work to figure out how we're working with the data. And now that we've put this into a list object and have an actual name to table, we can interact with this table much more seamlessly and intuitively than when we're trying to keep track of the indexes and where we are on the page with cell counts. I'll keep showing you some of the other really common properties you'll use here, which is that there's a list column object just like we have list of rows. And so we can do the same thing. We can say list column, index to that range that's on that just to show you what this is. And this is our second list column here we have quantity. Something really cool about lists columns. And this is one of my main reasons that I like to work with these lists objects when we're in VBA for automation is when you have lots of data. The methods we've done before and what a lot of people use is keeping track of either your column names, which is ABC and the letters all the way down, or keeping track of the number where each column is. So prices column three, timestamps, column four. But when the data gets really large, you start to keep track of column count. And it gets really difficult, especially if you're going to change your table around and delete or add columns, then column number 27 becomes something different. And if your code relied on using column 27 for something, you have to go and find all these places in your code to update the column index number. So one of the best parts about using a list object here in VBA for automation is I can take this two and replace it with the word quantity. And this is going to know the column name based on knowing that this is our headers. And it's going to know which column does is if I run this, it's still quantity. If I change this to price, then it's going to know the column titled price. And then if I do something like insert a new row here we have column one. I can run this. It knows that I'm looking for the price column, which is now over here instead of in column D on the spreadsheet. And this is a really common mistake that a lot of developers or people working with Excel will make, which is not utilizing this and using a number count or even the spreadsheet addresses. And when they changed something, then all their code won't work anymore. This is very common to the very first videos I had on named ranges earlier in this class. So that's it for this one. In the next video, I'll get into some of the more details about what we can functionally do now that we have our data in a list object. 54. 2.11.2 ListObjects - ListRows and Looping: And the last lesson we introduced to some of the very basic properties we have now that our data is in a list object. In this one, I want to give some examples of how we can actually utilize this list object. Do some very basic tasks will make up. So first thing I'm gonna do is just amplify this data. And so I'm just copying this and just repeating this data. So we have more information here. As I showed you before. You can see that as I add data to the bottom of this table, the formatting is not just moving along, it's not moving this alternating formatting because of the copy and paste. You can see from this little triangle here on the bottom right that it realizes that the table itself is growing. And so again, this name table is helping us with a lot of the work we do for data. And it's detecting what the range of this data is as we continue expanding it. We can prove that because we have this code on the right. And as we run through it, you can see as we select our table, that it realizes that data is now all the way down on row 29, and not just the first few rows that we have before. We can delete this column one that I added in the last demo. If you right-click here, I can do to bleed table columns. And now we're back to our original columns here. And so we had these different properties that I was showing you before. And I want to show you now that we have our list of rows. And before we are showing you how we could select a specific route. So if I don't select a specific row, even our list row's object without a specific row has a couple of things we can do with it here. One of the ones that I use all the time is this count property. So this is going to tell us the number of rows in our table. I don't think we can actually run this because this is a value. So it is not a action that this line of code will run. And so you see it's throwing an error here. Instead, I can say debug print, because this is going to be a value. So we're just going to take this value and we're going to print it out to our immediate window down here. So if I run this, you can see it's printing out the number of lists rows in this table, which is telling us is 25. So we come down here just to verify if I highlight these cells, expand this out. You can see the count is 25. So this is something I use all the time just to know how many rows there are in our data table. And again, the really helpful thing it's doing for us here is it's not doing something like including our header, this information over here. So when our data is not up against the top, it can be difficult for us to know how many rows there are very quickly. And so now we have an easy way to figure that out. Now with this information, just like before, where we use a loop and we use I as an index. We can say I equals one to n before we just put a large number here and we would escape out when we detect the end of the list. We don't need to do that anymore because instead of needing to detect where the table ends, our table object already tells us that if we're looping through the rows here, I is going to be the counter that goes through each row. And we can say it goes from one to the number of rows. So I'm going to say table that lists rows, that account. So in this exact example, our row count is 25, so it's gonna be I equals one to 25. And then we can use our I, our index counter to loop through each of these rows. And we don't have to like before, tried to do detection of when the data ends. Because we know when the data ends, it ends. When we get to the last row of the row count. I hear something I'm not sure if I've talked about in the past lessons is that I have this option Explicit up at the top. What that means when you see it is that I can't use a variable before I declare it. So if I do something like just saying print I. So you can see it's going to go through this loop and go from one to 25 here. And I tried to run this. It says variable not defined. That's because I have Option Explicit up here. If I remove this, it basically means that I can use variables without declaring them first. So even though I'm using I and I don't declare the variable is going to let me run this code. Some people including myself, like to use Option Explicit because it makes sure that you're keeping track of your variables correctly. So I have to declare, I give as a integer up here. I'm actually going to call this a long, which is just basically a integer that can hold more content. I won't get into that in this video. But i is basically just like an integer. It's a number. So as I run this, you can see we're looping through each row here and we're going through the counter and it should stop at 25. So you see it stopped at 25 here because it knows how many rows are in our table. Now we can take this index and actually do something with it rather than print out the index. So we can do something like take our table. We have our list of rows. If you remember, we had our index where we can choose a specific row. And we're just going to say, I don't have to select property. Instead, we need to be a range before we select. Now, if we look through here, we're getting to here and we have row one. And then as we loop, I becomes two. And now we're looping through all of our rows. And we did something similar to this. But again, we don't have to detect the end of the table here. It just knows that the data ends after row 25. 55. 2.11.3 ListObjects - ListColumns and Row Values: Now that we see we can loop through all the rows of this data, a lot of times we want to get the specific data in the columns as we go through each row. So looping through each row entirely usually isn't what we want to get to. Typically we want to evaluate the data inside the table as we're looping through the rows. How we can do that is as we go through each row, we also need to look at the column that we're trying to look at. We'll look at the data in a specific column as we loop through those rows. Let's run this again. We see here that we have row one, and so this is row one. And then we're just for the demonstration, looking at the range and selecting it so we can see which row we're working with. If you take this range, you can actually do a similar thing where if you put a parentheses here, and let's type the letter three here, we're putting an index inside the range. So this is an entire row of information. And when I put three in the range, let's see what happens there. You see what it's doing is it's taking this as the row of information and then the range is three, meaning 123. So we're coming over to the third column, and now we're starting to look at data specifically inside a column as we go through the row. So just to give an idea how we can look at the data here, let's put a debug print and again, range three dot value. Here we're selecting it. We don't really need this. It's just for a visual demonstration of what's happening. But let's leave that in here. And then we're going to print out the value that's in row, which is what we're looping through. And then we're just going to print out the value of range three, which is really the column three. So you see we have this value 20 here. Let me clear this out here. Here's 20. It's highlighting the cell first, so 50. So now we expect to see 50 here because we're on this row and now we're getting the third element of that row. So we're at 501116. So just as we expect, and as we look through here, we get all the way to the bottom and we have 115020. And now we're really looking at the data in specific as we move through this table. Widen this a little bit so it's easier to read. But we have this problem that I mentioned before, which is that I don't really like using this three over here. Because if I'm trying to do something to look at the price, and then I add a new column here. We have this problem where price is not three anymore. Now it's count for. And then if we wrote a lot of code, we have to come back here and change this three to a four or a bunch of things are not going to work correctly and we might not realize until an error happens. So now I'm going to delete this and show you another property we can use to solve this. I know things are getting a bit complicated here. If you can bear with me, This can just be a proof-of-concept and not something I would necessarily expect you to completely absorbed at this level in our class. If I come over here and before we even get into our loop, we're going to look at our table and look at our list columns. And if you remember, we can call out our price. And let's just pause over here. I run this. We get here, we select our price column. In our price column, we're going to debug print a lot, like how we have this list of rows. Giving me an error because I'm leaving this parentheses before the lines done. A lot like we have this property of the count of the list rows. We can take our table list columns, the price column, which is this right here. And then say index. As we come back up here, just like count returns a value for the count of lists rows. If I say the index of the price column, It's giving me three. We can't see it because I need to clear this out. If I run this, you can see the index of the price column is three. Now that we're doing this, if I insert a column over here and run this exact line of code again, I'll hit F eight. Now, it knows that the index of our price column is four. So basically we're taking our call out of the specific column by the column name and then finding the index of it. So if we take this entire statement over here, I'm going to copy it. And where there was a three, I'm pasting this statement which right now is four. Let's try to run this. I'm going to clear this out so we can see it again, but that was 16. Let's run this again. You see this is three, so it's still selecting the wrong thing here. Selecting our third column. I can do the same thing here. Replace this three with this entire statement that we have up here, which is giving us the number of the price column. So we expect it to be for inside that same parentheses where I've replaced the three. Now we're over here, 16202050. And the magic of this is now if I do something like delete this column, now price is the third index. And I continue running this. Here we are again and everything is working correctly. It knows where the price columnist. And I know as we start nesting these statements together, things get a little more difficult to follow. A lot of times I'll write it like this just to save lines of code. But just as an example. But this really is doing is basically saying price column. So I'll make a new variable here. More obvious what's going on here. I'm going to use along and say price index equals. And then take this statement over here, which is figuring out what index number the price column is. Then instead of having this nested statement with all these periods and properties in here, the range we want is the price column index. So this might be an easier way to think about it, whether or not you want to use this variable as a middleman or you want to combine two statements together right away. And we're replacing the column number with a variable and then detecting it based on the actual name of the column. So just to show you that this will still work, prices column three. The price column index is three. And now as we go through each row, we're gonna look at the third item inside that row. Looking at this 5011202050. 56. 2.11.4 Excercise - Delete Certain Rows: Now, with the information we learned from the last couple of videos, I wanna do an actual exercise here. So let's start to take an actual action and see if we can do something with this database on the concepts we learned about the list object. What I'm going to come up with is we're going to loop through these rows and we're going to be rows where price is either 1146. So we have this data that I copied here. It's a lot of the same data, but we have these values that are 1611 throughout the data. Let's use the concepts that we've learned to perform this task. So let's take a look our code over here and clean up some of it. So this is some stuff we don't need. In fact, let's just start from scratch and start with declaring our table. So that is the very basic thing we need. We have our table object here and we're not doing anything with it. For our previous videos, we can remember that we want to loop through each row and then we're going to analyze each row as we loop through it. I'm going to say I equals one. Table that lists rows, dot count. Go to the next I. This is basically a recap here we're gonna do our list rows, our index I, which is changing for each loop. Let's just select them to recap on our previous lessons. We'll go through here. And then we're going to look through each row here. I'm just going to stop this here. So we know how to do that. Now, we want to look at our price column. So I'm going to do this with the middleman variable just to make us more obvious, since I know this is a training class, we're going to say price index, like we showed in the last video. And we're going to call that a long, which again is just very similar to an integer. But I just generally use a long whenever I'm using a number. Say Christ, call equals our table, and then our list column, and then its price index. In this case, it's just going to return the number three because price is the third column in our table. And then now we don't want to select the entire row. We want to look at specifically the price column index. So after range here we're just gonna look at a specific cell in the row and not the entire row. So let's run through this again. And now you see what we're looking at our price here. Click through here. I'm going to stop this again. Now let's take this exact same thing, but instead of selecting it like we do here, we're gonna debug print. We're gonna, it's gonna grab this left side and again, selecting it, we're just doing it. So for our benefit of visualizing it over on the left, when you're actually running a lot of code, you don't have to select each cell over here. I'll show you that in a second. And instead of selecting it, I grabbed everything before the select statement over here. And I'm just going to type value. And we wrap this in our debug print. So we should be sending this stuff down over here to our immediates window. We see 1620. We're mostly just recapping what we did in our last video. Just to show you what I was mentioning is if I comment out this row so that we are not selecting each cell on the user interface, then this is still going to work because this entire statement isn't saying something like show us the value of the cell that's selected. And this is a very common thing that people do when they first start with Excel and macros is that they think that everything you do needs to be occurring on the user interface. So you might do something like select the cell and then show me the value of the selected cell. We don't actually need to do that here. Because we're not looking for the value of the cell that's selected. We don't actually need to select anything on the user interface and it will still work. So come over here and you see we're still just leaving our selected cell up and a one. It really doesn't matter where. And our code is still running over here, 501116. So it looks like we're over here. I'm going to make this even larger just so it's easier for us to see more of the code here. Now, let's work on our actual exercise. If we want to just delete the prices that are 1611, we need an if condition. We need to check for a certain condition here. We know we have the price. In fact, I'm going to make this more explicit. I don't always do this, but the more variables we create here, it'll create the kind of middleman stepping stones to make it easier to understand. I think we're going to say price as double. Double isn't just a number. It's a number that allows decimals. So that's why I'm using a double here. Because price, we're not using them right now. Everything is 0 sense. But if we had actual sense in these prices than it would allow for decimals to be stored in this variable. Now we're going to say. Instead of just printing out the price, where I say that the price equals. And then we'll pick the same thing that we're printing out, which is just a price in that row. Then we're going to say if price equals, let's just do 11 first. Then. And let's actually do this. We're going to print out the message. Price is flagged. Let's even take this message. We're going to append the index I, which is again our counter, which row we're on. We're going to loop through all the prices. And whenever the price is 11, we're going to send this extra message over here into our immediates window. In the meantime, I'm just going to turn off this other message so we don't get too confused here. And just for our purposes, I'm going to select a cell again so we see which row we're working with. It gave me a message here. If thought that there's a problem here. And that's really just because I didn't remember the foot, the end. If right here I've got the word. If. I loop through here, we're looking at the first row. The price isn't 11, so you see it skips right through to the end of the statement. Execute this line. Work our way down. Okay, now we're on cell over here, which is going to be 11. So as we check our price, it's 11. We entered a statement, price is flagged and we see Rome row 512345. Because we copy this data, it's actually in a pattern of bits. So I think this is gonna be row ten. And now we're at a price of 11, would jump in, and now we're at row ten. Now you're starting to see how we're gonna be able to do this. Now in our if statement will say, or price equals 16. And in fact, I'm just going to run this all the way through. I'm going to hit F5, which is the same as clicking this Play button here. And we're going to run through this entire thing. Which rows have we flagged? We flagged 5610111516. That looks like it's gonna be right. So we have five and then right afterwards is 16. And then this pattern is going to repeat itself over and over again. You see, we're doing the detection logic that we're looking for, which is, we're finding out every single row that the price is 11 or 16, and we're given the index of that row here. I'm going to purposely make a mistake here, which I've made when I first started doing this process. Something very similar, which is cleaning rows. Now that we've flagged the row, we want to take this row that we found, which is row I. Once we flag it, I'm going to say table that lists rows I. And what we want to do is delete it. There's no detection here. That's because I made a typo. I'm missing T over here. So now that I've typed the right object, which is list row, now I get these options of what I can do with it, which is delete. So let's see what goes on here. I don t think this is going to work correctly. Actually let me clear this out. I think something happened there, I didn't really notice. So let's start this again. We're looking at row one. We skipped over. Two, we skip over. It looks like I deleted a row, I think because I had the previous code running in progress. But let's just follow up where we are here. 50. That's not it. Now we're at price 11. Now I think we're going to enter our if statement. Because I delete a row, everything's shifted. So now we're on row four. And then we're going to delete this row since it's 11. And when I delete it, this row is gone. And the problem I see here, and you may notice this already is we are on row four. But as we go over here to row five, everything shifted up. And since everything's shifted up, the row over here, that's $16 is now row four because everything shifted up. Now when I run to check the next price, we're on 20 and our price of 16 for row four isn't getting evaluated. This should be deleted also. But since we deleted row for this moves up and then we already moved on to row five. We've skipping over this one row. So every time we delete a row, we essentially skip a line of information. Now this is leaving a 16 and it's really showing itself here, which is good that it's exposing. The problem is because we're supposed to delete two lines in a row. And so since we're always skipping the line after we delete one, that it's showing that the rule is not executing correctly. So we're gonna do the same thing again here, where we're looking at row a. Row eight gets deleted. 16 moves to row eight. And then on the next loop, we're going to already be on row nine. And so this 16 is never going to get evaluated since it moves up one. So that's our problem. A very simple way we can solve that is after we delete a line, we can just say I equals I minus one. So what that basically means is we're going to delete. In this case, we delete row eight, but then we're gonna move i back to become the value of seven. Then when we come down through this line and we increment i1, we're on row eight again. So when we delete a row, we know that all the data that we still need to evaluate is going to decrease one row. And we're going to basically back up one step. And then we'll evaluate row eight again, which would be 16. So let's see if that works. I'm going to stop this whole thing. Let's add our 11 back in here just to kinda rewind our information. I'm not adding this data here. So I'm just gonna put 11 here for our purposes, just for this test. So we're backing up here, we have 1116 all at once. So let's try this out. I'm going to loop through here. We're finally on 11. We're going to delete 11. This is four and the problem is we're jumping up the five next time, we're going to backup our index value I, one. So I is now three. As it goes to the next loop, it becomes four. Now we're back here on 16. And then we call it 16 and we're deleting it. So we flagged for, and then for again, because 11 was row four and then 16 was also a row four and they've both got deleted. Now we're still on four because every time we delete a row, we're backing up one index. And the big thing here is really, we're getting into the topic of a more complicated algorithm. And this is really going to be where the growth is when we are learning automation and programming and coding in general is a lot of the tutorial so far in this class is learning the different functions that we can do. The very specific lines of code. But the complicated part and where the real power comes from is how we can come up with algorithms on how to sequence the actions of this code together to perform what we want. So let's run all of this. We're going to finish running this. And here's another problem. We successfully deleted all the prices of 1116 here, but we hit an error. So let's see what that error is. Even though it looks like we completed everything correctly. We have an error because I is 16, so we're looking for row 16. But if we highlight all of these here, we can see that we only have 15 rows. That's because we're running this loop up until the end of the row count, which was 25, if you remember from our last video. But since we're deleting rows, the count of the rows is going down. But this thing is still thinks that's supposed to run this loop from one to 25. And as we delete rows, this table shrinks and shrinks. And then where these pads meat and causes an error is it thinks it needs to run the 25, it hits 16. But we've deleted so many rows that there is no row 16. So now let's just stop this and we're gonna do this actually a different way. So this was the solution to solve the row indexing problem. And this was achieved solution. I'm gonna show you how I usually do this. Just so I don't have to mess with this data. I'm going to change this rule. We're going to delete the prices where the price is 20 will fit to this data up later so we can do other exercises. But for now, I'm going to change this to delete equals the leap. Prices that are 20. Now there are tests is a little bit smaller here. We're going to keep looking at the data. Then the code at the same time. Instead of incrementing backwards, we're going to solve this problem in a simple, more elegant way here. And it's going to also solve all problems where we're looping through all the rows, but the row count is decreasing. Instead of going from one to the count of all the rows. Basically going from one and going down the list, we're going to reverse this. We can actually start with I equals the highest number. So in this case, we have 15 rows. If we run this again, the count of rows is gonna be 15. I'm actually going to take this and put it at the beginning. So I equals 15 in this case to one because we're going to count backwards 15 down the one. We can't actually do this and this will cause an error, I believe Let's try to run this. You see, we just skipped all the way to the end, none of this ramp. That is because we need to explicitly say how we're gonna do steps. So as part of these for loops with the index, we can add step minus one. And that tells it that each loop, we're going to step backwards. We're going to step backwards the value of one. Now we'll run this and we start at row 15. And then we're going to select it. So now we start all the way down here and we're gonna do the exact same thing. We're going to test the row and then we're gonna delete. So we need to change our role here where price is pointing just because we don't have the same data. And we see we skip over here. Now our price is 20, since we're going from bottom to top, we enter here, we flagged route 14. Now the nice part about this where we're selling both of these problems at once is when I delete this, 50 is going to move up, but we already checked out this row. And we know that it's not one of the rows we want to flag. And so when I delete this, this is real 14. We have no problem that the data underneath the line we deleted moved upwards. And so as we increment through from row 14, we don't have to check rail 14 again. Instead, we need to go to 13. Basically, this adjustment we made to solve that problem isn't needed anymore. Now when we go through the next loop, row 14, we go up to row 13. And we're going to check that again. And we see that it's 20. And then it's going to delete this row. But then when it goes from 13 to 12, we're going to be up here and we're still checking our rows in the sequence, despite the data underneath moving around, since we're moving from bottom to top, we're not affected by the fact that the data underneath the deleted rows are moving around. This up 2020. And then since we're going backwards, we're going to stop at one. And again, we're not gonna go downwards where stuff's changing and giving us problems. Instead, we're going upwards where the data is solid until we delete it. And so now this will continue to work and it's not going to run into a problem where as we cycle through all the data, that we hit an error because our row count, let's change that and we delete that. And now we're down to this very simple list of just our leftover rows in that ran, we've got all the way through without any errors. 57. 2.11.5 Excercise - Delete Certain Rows Lvl2: Now that we saw how we can clean up the rows, I want to just give a demo here of how complicated we can really start to use these rules as we lay them together. Again, I think we're getting very complicated based on where I expect you to be at our lessons at this point. But I want to use this as a video where I just kinda demonstrate how powerful this automation can start to get. So don't worry about following along too much. It's more of a proof of concept. So I took this data here and I added more data here. Just put some random stuff, some numbers for us to try to clean up and put some complicated rules against. Something I wanna do here is I just want to take a look and we're not actually going to use this in our data. A lot of times we won't have that our dataset. But let's do something like take our price and we're going to multiply it by our quantity over here. And I'm putting this over here just for our reference before we start this exercise. If I drag this cell down here, we're going to see for all these lines, I'm specifically not making it part of the table because it's just for reference that we're taking our quantity times our price, and we end up with all these numbers over here. Now with our numbers over here, Let's make up an exercise for us to do. We're going to say delete rows where quantity, price is a multiple, five. So we have this. So let's take a look at the things that would be multiples of five. Basically, that means if you divide the number by five, that you get a whole number. So I'm gonna change this over here and not a decimal point like this. If we come over here, we can go through and we see if it's not, let's see, we're gonna delete rows that are a multiple of five. How about we delete rows that are not a multiple of five? Not a multiple of five. So that means this one here will highlight this just for reference. So we're seeing these rows over here are not multiples of five. So I'm not going to continue doing this. But we just sort of see that if it is not a multiple of five, when you multiply quantity and price that those are the rows we want to get rid of. So I'm going to just hide these right now. We might not look at them again. I just wanted to give you an idea of what's going to happen, which is gonna be invisible to us here on the user interface. But that's the rule we're going to make. We'll come back over here to our VBA code. We already have the code we wrote in the last lesson, which is the leading, our price flag of 20. So instead, we're going to add some more logic here. I'm going to say price. We're gonna say quantity equals. We have to declare our variable here, dim quantity, as we could call it long or a double. Whether it's a decimal or not, we haven't used any decimals, but just in case we call it a double, we're going to need to know the index of our quantity column if we're following the logic that we used before. So we're going to say them quantity column index equals. We can just take from this row below it table that lists columns. Quantity, actually the whole word out. So that's because I asked him when he wrote the word dim here. So we're just declaring yet. We're not declaring it here. Sorry, we're just setting a value or not declaring it here. So quantity column index should be to, price should be three. When you use that information here, where quantity equals. And we're going to take this information over here. And then instead of the price column index, we're just going to be looking for quantity counts index. So we're gonna get the price, we're going to get the quantity. And then we're going to look for we just call it product, which is the multiplication of the two. We'll call that a double. Also. You may notice that I can declare multiple variables on one line. So that's what I'm doing here. You can separate it with cava and I don't need to use the dim call out anymore. And I can declare multiple variables with one line. So that's what you're seeing me do here. So product is a double. I'm going to say product equals price times quantity. So now what we were looking at when we were describing earlier is not the price or the quantity. We want to see if the product, which is the multiplication of the two, is divisible by five. You can search this. This is actually a different term, which is mod five, which is checking whether or not it's a multiple of five, basically doing the same thing that we were doing manually before. Which is seeing that if you divide it, Is there any remainder equals 0. So this is getting the remainder. When you divide the thing on the left by the value on the right. So as we go through this, Let's try this out. We highlight the first few rows so we can take a look and see if our expectations lineup variable is not defined here. That's because I did not declare this variable. So I'll come over here. And so now we have our price column index and our quantity column convex. Let's run this and see if it goes smoothly. Our first try here, oh, I forgot we're going from bottom to top. Which basically means it's gonna be hard for us to see what's going on here. So let's do our rule really quick. Just so we can see from the other direction, from bottom to top which rows are going to. Let's just grab a couple here. So we want multiples of five are going to stay. So all of these rows are going to get deleted. And then we expect these rows to also get deleted since they are not multiples of 5335 thousand are. So let's take a look at this product mod 549. We're seeing this 49 over here as we look at our products. So that's working correctly. And then we skip over it. Actually wrote this in reverse. Mod five equals 0 is saying enter here. If it is a multiple, we wanted to delete ones that are not a multiple of five. So let's change it from equals two is not. Let's start all over here. I'm going to stop this. Let's run this. We're back here at seven times seven is 49. Product mod five is not a multiple of five. And so now we're in here. We flagged row 36, and then we're going to delete it. Or product again, 76, delete, delete, delete. And then now we're hitting our first row that we expect our product is a multiple of 533 here. And then we skip out. So we're skipping through these rows here, hanging another route and we're deleting it. And I'm just going to hit play and run through all of this. See, we've deleted our rows where the product of the quantity and price is not a multiple of five. I just wanted to show this as a demo of how you can layer these rules together. And of course, the processes we can program can get much more complicated than this as we need to. 58. 2.12 Moving Data Add Row w ListObject: In our last few videos, we went over our name tables and our list object. So this was a bit of a detour from what we are creating before, which is this purchase form, which moves data from an input form to a data table over here. So now that we've gotten familiar with how to interact with this list object, Let's build this back into our purchase form and see how we can make sure that our purchase form will still add data from this tab over to our data table over here. First thing, let's clean this up and make it a little bit smaller, just so we can see the data easier. I'll right-click here, delete rows, and we just make a smaller table so we don't have to see all of that at once. Now we'll come back here. Let's change some numbers here, just so we have something else to look at and see if we can add it to the other tab. Line has been added. We come over here and we see the code that we wrote before for that button is still working here. So that's interesting because let's go back to our code for the button. I'm clicking the button, Developer and View Code. This is the code that runs when we click that button. And we have not updated this subroutine at all. Based on all the updates we've made regarding our list object. We have our validation from the previous videos, and we have our add line logic from the previous videos. If you watch those, you'll remember that the way this works is not using the list object that we've gone over in the last few lessons. But we are using a top left cell of the data called table purchases and using that as an anchor, anchor this so that we can see both sides at once. Here. We're using that as an anchor. We're counting down just a huge number over here for our loop because we don't know how big this data is. And as we saw with our list object, we no longer need to do that if we use the list object. And we count all the way down until we see our next blank, which is right here. And when we see our next blank, then we marked that as our next new row. And then we add our information into the next new row. So all the logic that we had before is still working, but it's the old logic. It's not using any of the benefits of this new list object that we've created, this name table on the Excel sheet. And we're still using this anchor and counting down, finding the next new row and then adding the information. One thing I want to show you is if we had created this list object misnamed table. To start with, we would not have this anchor cell called table purchases. And we wouldn't be doing this process where we're counting down the rows. And if we're working with columns, counting the columns over to the right, all based off of this anchor. So if we come over here to formulas and then Name Manager, we see we have table purchases and that's this named range here. Here is our named cable, our list object over here. Let's delete this because a lot of cases we would have started off using this name, the table, instead of using this top-left anchor process. Now that we know this better method, we'll come over here and we'll delete this. Yes. Now when we click into this cell, you see it's no longer named table purchases. Now, we're going to expect this process won't work anymore because as we just saw, it relies on the use of this named range. So when we click this, I think it's not going to be able to figure out what this is now that doesn't exist anymore. So we see that happened right there. And now our submit button to add to the data no longer works. So our previous logic, which relied on that here, no longer applies. So let's look at what we need to do to make this work with our list object over here. So we can just take all this code over here, and let's just start from scratch. So we'll delete all this and we need new logic now that we're using this list object from our previous exercise, will remember that we want to call it a table. And we want to declare the variable that stands for this table object over here. So we'll say table as list object. Then we'll set equals. We need to call out our worksheet sheets. Objects in the name of our name table over here is TBL purchased wise. I believe. We can come back here and confirm that by highlighting this, going to our table settings. And people purchase lines and confirm that. Now that we have our table here, instead of that for loop that was scrolling all the way down each cell and finding the next blank row. And you saw that if you have thousands of rows, you would scroll down thousands of rows and find the next blank cell. And we have put a placeholder of 99 thousand, just as a huge number there. Instead, I can do something. Like this table that lists rows. So let's try this out. This one line of code is just going to know where the next new row is and add a new row there. And I haven't told it what content goes in there. But because we have formatting on this table, I think you're going to see that the table expands one new row showing up in the formatting of the table, even though we didn't tell it what content to put in there. So I'm going to put a line break right here because we're gonna be focusing on this code a lot so that when we're testing this, I'm just going to run it and it's going to jump over here to our new code. So we added a new row with a simple thing like this. And this replaces our entire four-loop, that whole process that we had of scrolling down and checking for a new row and marketing. What number our new row is. The next thing we wanna do is figure out how to actually put content in there from this form. So now that we have a new row, I'm going to create another object. And we have a list row object. I'm going to call it L rho, Lists row. And you see just like list object and all these other variables have a variable type or object type. There is a list row object. And so now when I create is just because I'm in break mode over here. So I'll stop the macro and process. So we want to take this thing and this list row object, we want to become the new row that we add. So I'm going to say set L rho equals the new row that gets created. So this is going to execute and create a new row. And while it is doing it, as soon as it creates that new row, it's going to set that new row to be this object, the row variable that we just created. We'll see how this works. Because if I say L rho now arranged, got select, I'm going to run this. You see we create a new row after that line, and here we are with a new row. And then if I run this which is L rho select, you see L rho, R object is now this new row that we created. Now we can start to do something with that row. And you say range, just like we did from our last exercise when we were checking the values of specific cells in that route. If I said range one dot value equals, I'm putting info into this table now. And this is how we can reference, just like in our last lessons, the values of each cell in a row. Only instead of just reading the value. And last time we were doing some cleaning of the data by reading the value. We can also use this same concept to put data into that cell. So if this logic, you can start to see how we can combine these concepts and move the data from our form into the new row that we create. So let's start that process when I say dimension item. And I'm just gonna go ahead and create variables for each of the fields on the form here, we'll call quantity along a double. I forgot the word as here. We'll declare these variables over here. Using our range names. That value. Our quantity is quantity. That value. Let me just make sure I have the right name there. That's going to be formed price. I'm just guessing here, but if we name things correctly, it will follow that pattern for a price. And then now as we saw, we can then place content into the row using this range index. So if I take this and we put items in our first column, quantity in a second and price and our third, it will look like this, 23. And over here, I'm not going to pass it a string. Instead we're going to pass it the variables that we used as middlemen here, quantity, price. And then we have a timestamp over here, which we don't get from the user form. We get the timestamp from just our VBA code itself. So we'll say VBA, which is a built-in VBA function that'll get us our timestamp of the moment this code runs. So let's try this out. I'm going to hit F5 to run. As an error there because I made a typo at F5 to run, we jumped down to where we put our breakpoint and I'm going to use F8 to step through the code. So now we're declaring our variables. Item, quantity is five, prices eight, or adding a new row. We don't really need this, but we're selecting the row that we use for that demo. And then our first spot in that row is the item, quantity than price, than timestamp. And the line has been added. So we don't need this, which was just selecting it for us to see. Let's see, I'll finish running this line and then let's test out our button again. We hit Submit. I still have my break point here, so it's stopping over at this line. So I'm going to turn that off by hitting F9. I could have clicked over here also to toggle on the breakpoint on and off. I have to finish running over here. And it says the line has been added. This up again. Just to see that something changed. Here. You see we're able to add a new row to our data using this list object without as complicated of a process as before that we were doing without the list object. Another thing from our previous lesson that I mentioned was that I don't really like to use these numbers right here. Because the problem, as we saw before, is if I add another column here, this isn't going to work either. So I'm gonna hit F5 and just run this. A new line has been added and you see everything's misaligned. Now, my price went into third column and my timestamp went into my fourth column. But this isn't working correctly anymore. So to solve that problem, we'll do the same thing we did in the last lessons, but we'll just build it into our form here. I'm gonna show you the long way that we did last time. And then we'll build this right into the code. But let's say dementia as well. Quantity index as well as long timestamp column index. So we're going to use these variables. That's just a stepping stone to get to the final result here. When I say, I don't call index equals. And then we have our table and we're using our list pounds, and we can call these out by name. And the list of columns by name has a index number. So now we can use this process to figure out which column we're working with based on the actual name. So we'll do quantity that incorrectly. We'll do quantity, price timestamp. And we want to match this with the actual call out on our table here. So that's item quantity. We have price in timestamp. And then now, instead of putting this number here, 1234, we can line these up item called index. So now we're actually figuring out which column we're trying to work with here. Without having to type in the number directly. The code itself is going to figure out where the column is based on the name. We pass it for the column. So let's run this through here. And you see our item column here is one. Quantity columns to price column is four because we have this junk column we added, and then the timestamp columns five. Now these numbers aren't hard-coded. That our process here is figuring out where each column is while it's doing the process. And now you see everything is working correctly again. And it adjusted for that new column that we added without having to come back and update the code. You see here. The benefit of this is if I come over here and I delete that column, we don't have to update and change the column indexes anymore. We can run this and we still have a new row that gets added right here. What I often do is to save time and not do all of this with these variables storing the index number. You can put this information directly in these parentheses. And it makes the line of code a little bit more difficult to look at because we have these really complicated lines with a lot of nested information. After a while, you just kind of get used to looking at that. And there's some ways to make this a little bit simpler, but this saves the time that we took to create these variables. Here. We're just doing the exact same thing only we're not using these in the middle to pass the values downwards. I'm just going to use these commands directly where I want to use them. Try this out. Hit submit an 11, and there's our new line. 59. 3.1 Quoting Tool Project - Intro: Hi everyone. So I wanted to change the project that we're working on here in our examples. The project we were working on before it was a basic purchase warm. And then I want to change it over into something that I have a lot of familiarity about and that we could build out all sorts of different features as we go through our lessons. I want to change this to a creator. And then we can create a lot of different processes off of this idea of a tool that helps a business create quotes. To do that, I just wanted to shoot this one video on framing out the very beginning before we get into any of the actual VBA automation code. So let's print them out what a quick crater might look like. And I'm going to start from complete scratch here. So you see we have book one with an empty Excel sheet. And we'll go from there and we're just going to fly through some of the things we covered in our past tutorials here. So we're going to save this and we know we're gonna have macros in there. So let's go ahead and save this file wherever we're gonna save it. And we want to save this as an XLS, a Macro Enabled Workbook because we know we're gonna put macros in it. We'll put a label at the top. And let's just sort of envision what inputs somebody would have while they're creating a quote. So you might have something like a customer. Something else we might have is jack name with a person that we are talking with who requested the quote. Typically, you might do something like receive an e-mail from somebody as a request for quote, then might have something like the line items that are being purchased on the quote. So we'll have line items here. And you'll have your line number. And you'll have your item number. And you'll have a description. Quantity. Unit price will say unit price. And we'll have your extended price, which is the total price for that line. And so this is going to be more of a table. And for one quote, you can get more than one line item purchased per the quote. So up here, we can add a quote number also, because we'll say the number is our first quote. And you're buying something like product a. Product B, you're buying five of these, ten of these. So we learned before. Then we can turn this into a name table. So we're going to format this as a table. Another shortcut you could do is Control T. We'll also create a table out of here. And you can say my table has headers and I click, Okay, and you see it created our lines table into an actual name table here, our list object that we're going to use in our VBA code. Let's improve the looks of this a little bit. So let's stick to the basic theme I had before. So I don't have to think so hard about the colors here. We'll just do black and white here for our fields. Will stick to this theme for the table. So we'll make black headers. And nice part about these tables is you can just choose different colors. And it'll theme it for you. Let's make this form look a little better and we'll remove the grid lines here. I'm going to create some borders over here, which is kinda leave it looking like this. And now we have something that looks like a basic form similar to the purchase form we were working on before what we're going to frame out this new project for creating a quote. So I'm just going to stop this here and we'll continue on in the next video. 60. 3.2.1 Quote Tool - Create Folder: Okay, Now that we have a basic quote form over here that we framed out, let's imagine what might happen when a business receives a request for quote from one of their customers. They might get a request for a quote through an email, and then it comes with all these extra files. Or you might want to just save that email itself that might come from something like Microsoft Outlook. What kind of stick to the Microsoft products here for our demos. So we enter Quote number one. Let's say we're keeping track of our quotes with a quote number here. And we might wanna do something like create a folder. So right here we have our co-creator file that I'm working at now. And you might have something like files. We'll create a new folder here. And we'll say quote 000001. And we receive our first requests when the system starts up. And we might want to drag our request for quote files and drop them in here, whatever our customer sends us, that is information about the quote they're requesting. The first feature I want to try to build here is a way to automatically create these folders. Will do something where, for example, if we type in Quote number two here, we're on our second quote. And then we'll make a Create Folder button so that we don't need to manually create these folders here in this folder system. So let's get started on that will come in here. We'll make a button and we'll call this button Create. So now if we come over to our macros here, we don't have anything because this is a clean workbook that we just started in the last video. So we don't have any modules or macros recorded. Let's insert a new macro or rather insert a new module, which is a section for us to create some macros. And we'll categorize this. We will call this file management as our module name. Let's start on a new subroutine here. And we'll save that for a minute and describe what this does. To store files. This is just a good practice, is to put a comment to describe in detail what each subroutine or function might do, especially if it's not something as intuitive. So I just want to show that, although this name is pretty descriptive. So at first I just do something like say creating. And let's attach this button to this macro that we just created. And so because we create this subroutine, we have this great quote folder. And now I've assigned this button to work with this subroutine, and we pop up this message and we're not doing anything else yet. So we're going to create our quote folder, in this case using this number over here. So let's create a variable that's going to store this quote number. Call it quote No. As. And we'll say as a long for now. And let's get this from the interface. So now that we've declared that variable, you can say equals range. And we need to get this cell over here. So this cell is before, but may remember from our previous lessons that this is not a good practice. We could do this. But then if we move things around or insert rows, the quote number field might not be B4 anymore. So we're going to call this quote No. Now when you hover over this cell, you can see that it is a named range, called Quote number. So we can do this, but let's just rearrange this. We're going to build this thing in steps. So I can keep demonstrating each concept as we go. I'll change this a little bit so that we can see more of the code green quote folder for quote. And I'm just putting the string together to improve our message so we can see what's going on. So now when I click this, we have created a folder and I made a typo there I meant to type for Quote number. And so when I run this fur coat number two and you see where successfully pulling the value from our interface here. Now, we want to create a folder in the directory right over here. In this case, there's different things we can do to make this a little more intelligent. But I'm going to start with something more basic as we build up our concepts here. So let's say we want to create a variable for what the path of the folder is that we want to create the new folder. So this isn't a new folder yet. We want to tell it where we want to create this folder, which is in here. Similar to knowing where you want to start here before you do a right-click and start a new folder. If we were to do it this way. So we want to get this path right here. Say folder path as string. And then we'll declare this folder path. And for now, I'm just going to hard code, which we might change this later. And I'm just going to copy and paste this here that I copied from this path up here. Now we have our folder path. We want to figure out what our new folder name is. So we're doing all the things that we need to do manually. We know what folder we need to start in now and we need to figure out what the name of our folder is. So if it was two, for example, we want this notation, but of course there's one would just change to it too. So we can say folder name. We can say new folder name, be more descriptive string. And I will say new folder name equals. And then our notation here that we see on the left is Quote number and then 00000, we're using six digits here and then two. Of course this isn't what we're actually going to do. We need this to be a variable. So we might want to do something like this. We know we have our quote number up here. But we have this problem that when we get up to our quote number of being ten, then we're going to have an extra 0 here. So how can we make this six digit number adjust as we get more digits in our quote number. Even though this will work for now up until we get till ten, Let's just test this out. And so we'll deal with this later. Will again move our message box farther down, creating new folder. And we'll say our new folder name here just to test it out. And I'm going to run it. We'll see creating quote folder. We have our zeros here. And that is because we left this blank. So let's assume we're supposed to do to here. And if I click this quote number two. So now we've created our folder name, but we do have this problem that if this was ten, we're not adjusting correctly. We wanted a six digit number and now we've pushed this to become seven digits. So what we can do is remove this and we just want to append the quote number here. If we run this, we see ten. And we need to force this to become six digits. So we can use this format function. A lot of times. These are built-in functions as part of VBA. And so if I type VBA, and then period, you see I get a lot of built-in functions that are just part of VBA. One of them is format here. And as I do format, we see that we have our expression, which is our number, and then the second parameter, which is in brackets here, we have the option to force the formula. So if I put in six zeros here, is going to know that the format I want is a number with six digits, whatever is in here. So for example, I can show you down here in the previous window, I'll do a debug print and say 123123. So we'll do six digits here. I'm missing my format function. So I want to type format here. And then as I hit Enter, you see this has taken the one over here and then made it in the sixth digit format. And then the big difference here is when I type ten, and then if I click Enter or press Enter here, we have the number ten, but again forced to the sixth digit format. So now we can do this. And the same thing we just demonstrated here applies where we have Quote number and we have ten in the sixth digit format. And then if we were at two, we would still have this six digit format here. So now that we have our new folder name and our folder path where we're going to create that new folder. You might remember from our previous video, we have this make directory command, which is going to create a new folder. And then we opened this and this is the path that we need. So let's construct this new variable before we use this. So we have our new folder name, but let's make a new one just to make everything really clear. New folder. If I was making this tool, I might not have all of these stepping stone variables to slowly build everything up. I might combine this stuff with fewer lines of code, but because we're doing a learning lesson here, it's more clear to create all these stepping stone so we see what's going on. We want our new folder path here to equal our folder path and combine that with our new folder. And I already know that there's an issue here. So let's show that I'm purposely leaving something out here. So if we do a debug print at the end of this, in fact, we can even use our message box would keep moving this thing down. Creating quote folder. And we'll make this the new folder path. I'll put a new colon here. And if we run this, you see as creating our new quote folder, we have our new variable, that's the folder path on the left, combined with a new folder we're creating. And what we noticed is we are missing a backslash over here. So if we came in here to quote folder one which we created manually, we have this backslash that's missing. And that is because when I create a folder path over here, I did not include a backslash. And then now that we have this backslash, we have our folder name that doesn't have it. We could have had two options here. We can either leave it like this and put the backslash over here because we're going to append these together. Or the option, I think it's a little more clear as putting the backslash on the part on the left, but we have both options here as long as the final result has the backslash. So when I click this, we have what looks like now the new path of the folder that we want to create. Now that we have that, we can use our command make directory. And we want to use this new phone or full path string that we've created in, it should make a new directory by this full path that we've just created here with our code above. So let's create a new folder. Create a new folder here. We'll click Okay, and then say anything. But if we back up here, we see we now have quote folder number two. Just for clarity, we might say Message Box folder has been created. We'll do the same thing. New folder, full path. And we can even remove this message. So we'll press this button. Let's say we have Quote number three. We'll click Create Folder. New folder has been created. Here's our message box confirming that it was all done. And here's our new folder again. We'll just touch one thing up here. Just a bit of clean up. I'm going to add a VB ELF character, which is a line feed. And that would just make this pop-up message you look a little bit cleaner. So we'll actually deal with this in the next lesson. I'm hitting an error because it's trying to create a folder for quote three, but that folder already exists. We're going to handle that in the next lesson. For now, let's just go to quote For will run this. And we have our pop-up message that looks a little bit better now with our folder for quote, for 61. 3.2.2 Quote Tool - Check and Open Folder: In our last video, we created this button with a function that creates a new folder based on our quote number. So if I say Quote number five here and click Create folder. You can see it says the folder has been created. We click Okay, and we go check on our folder over here. When I open this folder up, we see we have a folder for quote five here. The problem we saw at the end of last video. If I click this again, we have this error here. This is saying access error for a fire or path. But this is being thrown because the folder already exists. So I'm going to click stop here. This is a very similar error that if you did this manually, if I created a new folder here and said quote 000005, then the folder already exists and windows itself is going to throw this error here. So I'll go ahead and delete this. But VBA is essentially trying to perform this action and it's getting an error of its own. So let's update this so that we handled that situation. We have this line of code from the last video, which is the line of code that creates a new folder. So before we create a new folder, but we wanna do is essentially check to make sure this folder doesn't exist yet. The way we can do that is with a function built into VBA here called DIR for directory. And we have our path name. So we want to enter the path that we're checking here, which in our case is held in this variable called new folder full path. And as we use this directory command, we're going to use the second parameter, which is the type of file or path. And we're going to use VB directory since we're checking whether a folder exists. And what we're going to say is if it equals blank, if the result of checking this path is blank, that means the folder does not exist. So if it's this, then I'm just going to say folder does not exist as a common here. This isn't code, but I'm just kinda marketing our sequence of actions here. And otherwise, holder does exist. So we have this situation. And if the folder does not exist, then we can go ahead and we can go ahead and make the new folder. Otherwise. For now, let's just put up this message box that says folder already exists at the following path. We'll do a vb line feed just like we did before. And we'll use the new folder path here and tell the user that we're not going to create the new folder because of this problem. So now let's try it. I'm gonna hit F9 just so we stop here and then we can step through the code. So as I hit F5, we'll stop here. We have our new folder path. Everything is constructed. Then. Now you see, because the folder does exist, we have Folder five, which is the one we've already hit the error on an salted it exists. And now we're going to get this message box saying the folder already exists. Then if we change this to six, Let's run this again. I'll hit F5. So we run this code down to the break point, and then now the folder does not exist. And we're going to go ahead and make this new directory. And so at this point, the new folder should already be made. And here's quote six. And then as we run it, we get our normal message box that we want to come up when this runs without us stepping through the code. If I hit this button, it says we're on break mode because we're still in this execution mode where we're stepping through. I'll stop the macro and now we can use this button again. Folder already exists at the path for quote six. You can see we actually doubled up this message. So let's just show you this sequence that I didn't fix is we hit this notification telling you that the folder already exists. But then it continues through our procedure here, and then it tells us the folder has been successfully created. So we only want to notify the user that the folder has been successfully created if we are creating a new folder. So now we'll stop this, will remove this and we can try this again. It tells us the folder already exists. Then now when we change this to seven, it's going to say that we've created a new folder seven here. I'm just gonna go ahead and clear all these folders out. We're creating a lot of junk folders here. So we'll start with one again, and we'll create a new folder. And the folder for quote one now exists. One more feature we can add is instead of just notifying us that the folder already exists and that we won't be able to create a new one because we don't have to. We can then open the folder if it exists. I'm forgetting what the command is to open a new folder. So I'm going to open up my browser here, and I'm going to type something like VBA, Open Folder Path. We'll come over here, look at the answer. And we have our code right here that is calling our shelves. So let's take this code and we're going to open the folder here. And so we use our Explore. Explore is our folder window over here. This in Windows is called our file explorer. And then here is the path we're trying to open. And from our example they had this path. But we really want to remove this and we can use new folder full path here. So let's see if this works. Let's step through our code again, F5, and then we'll step through the folder does exist because we just created it. Then we have our message box saying it already exists. And it runs that line and you see it opened up our folder path that we had constructed before, which is for quote one shown here. So we can backup one and we see we opened up this folder. And we can set up this situation. Not only will it open the folder if the folder already exists, but since we're creating the folder, why don't we open it up anyways, right after we create the folder, because presumably you're going to use it right after you create the new one. Let's test this out. We're going to hit Create folder. The folder already exists. Then it pops up the folder. Then if we do a quote number two, which is a number that doesn't have a folder yet. The folder has been created. And then here it automatically pops up the folder after it gets created. And when we come back here, we see that we have our folders for Quote number 12. Now, just to clean this up, because we've created this function where we are also opening the folder if we create it or even if it exists, we'll change this button to say create slash open folder. It will make this button a little bit wider just so we can read the full command. And this way the user can see that we're both creating or opening a folder. 62. 3.3.1 Quote Tool - Add Line UI Setup: Looking at our quoting tool, the next feature I want to create is a way for us to add and manage line items on this quote. So you have one quote, you can have Quote number two. And then on this quote, you could be buying one or more things, and those would be line items. So here for example, we're showing that we would be buying product a and product B. So there's one quote would have more than one line item. What will create here? Before we get to the automation is just setting up what this user interface might look like. So we'll call this add lines. This is managing our line items. And then here we'll call this mine. This is taking the formatting because it sees this column. Excel thinks it knows what format and we want. But let's just make this normal for now. In fact, here we'll make a cell style normal so that we don't have Excel automatically change this for us. We'll say item and we'll say quantity. And these are the things we need to add a line, but we're basically just making a user form that is going to add rows to this table below here. So even say unit price for example, I will add more as we think of them. I can take this format here and I'm just going to copy this down so that we have this similar input. And we'll create a new button here. And we will call it. I'll just hit cancel here so we don't have a macro that's attached to it yet, since we didn't create that macro yet. But we're going to call this button Add Item. So when we fill this out and in-between our first video on this one, I decided that we're going to start to sell ice cream at our shop here. And we'll say we're going to do vanilla. Add a new row here. We'll say units is gallons. Will sell one gallon of vanilla ice cream here are unit price is $10. Let's say. We'll turn this into currency format. Then when we click this Add Item button, we want to take this information and add a new row to our table here. We're setting up the form for this function that we're going to have. And this is going to need to detect our next row and add a new row here with the supporting information. So we'll essentially click this button. It'll have to know that this is line three. Item we're adding is vanilla ice cream. The description will be vanilla ice cream. Actually maybe we'll change it to something like this, where our item number is one. Now that we just assign our items sequential numbers here, one through whatever we come up with in our item will be one. Vanilla. Vanilla ice cream or quantity will be one. The units will be gallons, or unit price will be ten in our extended price in this case will also be ten. But if we had a quantity of two, for example, then our extended price is our total line price, our unit price multiplied by quantity being $20. In the following lessons, we'll design the code to make this button perform this action here. 63. 3.3.2 Quote Tool - Add Line New List Row Part 1: Following up from our previous video where we were setting up the form here too, now, eventually have this functionality where we're going to enter information about the line we want to add to our line grid and click this Add Item button. Let's build that up. So we have our modules here, one for file management where we put our code related to opening and creating folders. But let's separate things out. So we'll create a new module here, and we'll call this line management. So keep with that theme. But we're going to have other things here related to managing this lines grid here, we'll keep our code altogether in this module. So let's set up a new subroutine and we'll call it. Line-item. Will frame this out. And we'll say this is going to add line item two lines table. From our previous video. We know we want to take this information and then add it to a new row of information here, there's a bunch of ways to do this, but the way we're gonna wanna do this is to make this a name table. And we're going to use the concepts that you might have watched in the previous section that I titled moving data. So that's another group of lessons for moving data around. And we want to use a list object, which is going to call this a name table. And we're going to use a lot of the properties of this being a name table to manage our, its rows and to add new rows and do other functions we're going to eventually use. If you're not sure what I mean here, you can go back and look at the lessons titled in the moving data section tagged with the list objects, video names. So what we're setting up here is knowing we need to add this information down into our grid. We need to get this information into our code so we can work with it. So let's create some variables to hold this information. So we're going to need a variable called item number. That's gonna be a string. We're going to need a quantity. For now. We'll say that is a long, which is basically a whole number. And then our units is a string. I forgot to add a space there. It looks like it added it for me. Then I have unit price, which is dollars and cents. So we're going to make that a double. So basically a number that can hold decimals. Now that we have these four variables setup, we need to get these from the interface, just like we did before with a quote number, say item number equals, and then our range, which in this case is B9. But since we don't want to type the cell address and work with that, we want to give these cells names so that they are defined even if we change things around. So we'll call this cell item number. We'll call this one item quantity. We'll call this one item units. We'll call this one item unit price. So now we've created a bit of a naming theme where stuff in this section starts with the word item. And it's fairly descriptive names here. So item number is item number. That value, quantity equals range. Item quantity. Units equals range item units. And unit price equals range item. Unit price. Not value. I believe we got these right. I made a typo here in Price and I'm just going to run this one's even though we're not actually doing anything other than setting these variable values, it'll tell me if something went wrong. And so that's just a quick check to show that it didn't tell me. It didn't throw an error to tell me that these names weren't recognized. So that's a good sign to start with, at least. Now what we wanna do is add this information to be a row down here. Again, if you look back to those past videos, I won't go over it again in detail here, but we can use this here, which is a name, the table. And we're gonna call this table lines. Now this table a name called Table lines. And we can use this list object to add rows and do different things that you would do it with a table of data. This is to avoid another way that we could do this, but which is a little more challenging, where we'd have to scroll down, maybe using a loop to detect what the bottom row is so that we know where our Excel spreadsheet row number is to add our next row. So we can avoid that by using this name table function that we now call it table lines. So the way I can use this table is similar to how we declare a range with a variable. We can say table lines as a list object. Which is the VBA object for named tables on the spreadsheet. We're going to say set cable lines equals and we have this sheet one here. Really what we could type is Sheets, Sheet1, that list objects. And then say tabled lines, which is the name of our table. So this should work just to show you, I'm going to do table lines and we'll check this. I'm going to say range that select. So we have our table here. We're gonna do the range and then select it just to see if we get the right thing. And as this runs, you see the very last line of code found this table in selected it. Another thing I don't really like though, is that this says sheet one and we have a direct call out here. And Sheet1 isn't a great name as we're making a robust tool that this is not a descriptive tab name. So maybe I'm going to change this to main. And that way we don't have something so generic like Sheet1. And so now that we have made, we'll see if this works. I'm going to run this again. And you see it is getting this name table and selecting a correctly. So we know our table lines. List object is the table down here. Now, just to show you, I can say table lines, that list of rows, that ad. And when this line of code runs, I'm going to create a break here and run it. If I hit F8, when we run this line of code, it knows where the bottom of the table is and it adds a new row. So now I'm going to backup here. To make things a little bit easier, I'm going to create a list of row object, list of rho. So this is a new object here. And I'm going to set this list row and combine this together with what I just demonstrated. So essentially this code right here is going to add a new row. But then at the exact same time, it's going to set this list row object variable as the new row that I create. Now I have this situation where I can say lists row, select. And this is just for demonstration again, where I'm going to create a break here, run. This line, creates a new row and creates that cross-reference where L rho stands for the new row that was created. So now when I select it, you run this line of code. You see our L rho object right here is this row. So now I'm going to stop this here. And now that we have an object that stands for the new row that we just created. We're going to use this to populate the information into the new row that we create. So here we can say L rho that range. And again, if you watch the past lesson, I go into this in more details. But basically, I want my item number up here to go into our second column, which would work if I say this equals item number, which is our variable we declared up here. So we're going to create a new row. And then we're going to say the second index. Which of this row, the second index or the second cell is here. We're going to place the item number. So let's just run this. You see, we stored item number in our variable and then created a new row in place to end the second index. So now I don't want to use this to, and instead, I want to figure out the column by name for reasons stated in our previous video. And I'm going to say, instead of two, I'm going to say tabled lines that list column item, because item is the name of this column over here. And this column has a index parameter which will return the column count of the column titled item. So this is the same thing as saying too. But the benefit is that if I added a new column in here and it got shifted around, this would return the new location of items. So it wouldn't always say to, it will dynamically be figuring out where the item column is. Let's test this out actually, and we'll run this and you see the same thing worked here. I'm just going to delete these rows so we don't end up going off the screen. And we'll continue building this up. Now that we saw this is an easy way to add the item. Maybe not so easy, but it's a way to add the item. We can move on to the other fields that we already have, such as quantity. We're taking this in placing it here. And this is our column name. And we can continue this trend where we're going to say units and unit price. So here we have units. Take this, place it here we'll get the value of units. We'll take the unit price, which we have to scroll over before unit price. And now when we run this, we've taken all this information, stored it, create our new row, and then placed it into here. So 1234 elements here. And I'm just going to make this aligned in the center, so it looks a little bit better. Maybe I'll even do it to the left here. Then. Now we have this other information here that we didn't fill out yet. So let's work through each of these one-by-one. Our extended price isn't from the input field. At least it isn't yet. But maybe we can do that. So let's add a new row here. I'm just going to make some space and we'll say extended price. So we can see this live. I'm going to just make this a copy for the sake of formatting and getting those cell borders. But then this is going to be a formula in our extended price, is our quantity times our unit price. And we'll make this a currency. And so this is $20. So if we make this five, then this will be multiplied out. Something I'd like to do here is whenever I have a formula in a cell, I like to make it gray. So the user can obviously see that they shouldn't type into this cell that is going to be calculated. One little thing you might notice here is when you create Named cells, like we did earlier in the video, that instead of saying sell, it uses the names we gave it here. Now we have another cell and we can call this item extended price. We can do the same thing here, but we'll create a new, a new variable called extended price as double setup. Same thing equals range, item, ended price. That value. We can create a another reference as we're passing this information into the new row, we create extended prices here. And our column name for extended price comes from here. And this is where we put our column name. So let's run this. We see vanilla, all this stuff. And we have our extended price of $50 in this case. It actually, I'll save it for the next separate video where I'll go over how we can create some of the supporting information. Because we want to take some of the info and make it so the user doesn't have to type it in. We can start to create something like a lookup where the description in, for example, the units is a lookup based on which item we select so that the user doesn't have to type it in themselves. 64. 3.3.3 Quote Tool - Item Data Lookup: Now in the last video, we created a new row and put the information from our add lines form down into that new row. But then we noticed that we're still missing some pieces of information. So we have our extended price, which we did at the end of our last video, but we still have description and line number. And another field that I mentioned was the units which is in gallons. So something we wanna do here is not make the person type in gallons and we don't have a description the place in there yet. So let's deal with these. What I wanna do is make it so that when a person chooses their item, that something like the description and the units for each item are always consistent. And so since there's a direct relation that when I choose, for example, my vanilla item, it's always going to be the same written description. Then I don't want the user to have to deal with that. So for example, I might put a row in here. We call it a description. And the straightforward way is to just do the same thing we did with these other fields. But then the user is stuck needing to type in the description. They can be inconsistent and it's just extra clerical work for them. So what we're going to make this do is make it so that when you choose the item, that information that can be directly related to that item will automatically get filled out. So the way I'm gonna do this is typically I'll create an extra tab here. And I call it underscore data. And it's just going to hold supporting information. So I'm going to say supporting information up here. And we'll make a table. I'll make it up here and we'll call it item. Will say item number one. Item description. I just used the word description here and we'll say, what I'm setting up here is a DataTable where I can say something like this. Where the number we used before, which was vanilla, will have a description saying ice cream. Like down here, I'm pretty sure ice creams to words. And then we have our units, which is in gowns. And just as an example, we could put something else here, which is to say, maybe we'll have another item we'll call to, we'll call it spoon, where we might sell plastic spoons that go along with our ice cream, let's say plastic spoon. And we're going to say, this is sold in whatever units these are pieces. Now we have a table, and as we showed before, I like to use these named table. So I'm going to hit Control and tea, which sets the range I had highlighted to become a name table. So I'm going to say my table has headers because we do have headers in the range that I highlighted. And now we have this table here. And I'm going to call this April items. Now that I have this, what I can do is take my items and make it so that the items that we choose in this field can pull from our items that are here. So this isn't really a macro or automation thing. This is a Excel feature that we have that you may have seen before. And if I come over here, let me back up here. If I go to the Data tab, I'm highlighting this cell. And then over here I have this data validation field. So I'm gonna click this. There's a bunch of different ways you can validate the information in this cell. And I'm going to choose list. And I use this all the time. And this is going to create a drop-down list. So there's a few ways I can put information in here. I can do something like say Yes, Common know. And this is a comma separated list. And as soon as I do this, you see we get a drop-down, which lets me choose yes or no. But we don't actually want this to say yes or no. What we want this to be is if I highlight this, I'm gonna come over here and highlight these two. And you see it shows our range that I just highlighted. This is the way that most people have used this in the past. If you've utilized this tool in Excel, where we have vanilla and item to our spoon here. We're actually going to change this a little bit because this is a bit of a tangent. But one problem that we're going to have here is if we add another item, chocolate ice cream comes in gallons, then you'll notice that this field did not expand. And that's because we selected this range over here, which is just these two cells that I highlighted. So a lot of times you'll see people do something like highlight all of this. Just so as we add more rows to our data over here, like let's say we add four, add four, strawberry here. We'll work our way up. We have this field, but you do still have this problem where we ended somewhere. So you could highlight all the way down. But this isn't the best way to do it, in my opinion. Instead, we can use this other notation here, where instead of having this range, which we had to select a range here, I'm going to say indirect. Then I can use the names that we gave, the table and the column. So if I say in the rec, I could say TBL items, which is the name of the table, this name table that we set here. Then in these brackets, I can put the column name. I have the arrow in this kind of, this formula acts a little goofy. If you hit the arrow keys, it will select another range. But I can say the column is item number. So an indirect, I have my table name here and then the name of my specific column. And then this will know that I'm talking about this range of information which is in the table and then the specific column. So I'll click Okay. Then you'll see this is still working the same way it was before. All we, we didn't need to put a specific range and I can do something like add five here. Let's see, let's come up with another one. Would put it in such butter pecan here. And then now we have our other selection. So this is more of an Excel trick than an automation tricks so far. But now we're going to add some more formulas here. Now, we can use an x lookup formula. And in the earlier sections of this class, we should have more videos on these different topics. Specifically, now we're just utilizing them for this actual project here. And so we can use an x lookup where we're going to look up our item. We're going to look that up in our item number column. And then in our third parameter, what we're going to return is our description column. And then if there's no match here, we're going to say not found. And one cool thing is that when we're using an X lookup against our named tables, instead of having a bunch of ranges which are hard to read like our cell coordinates. Instead you see that it realizes that we're talking about our table and the column of that specific table. So these are continued benefits of using named ranges and named tables instead of just using cell coordinates like A1 through C ten or something like that. As I showed you before, I'd like to make any cells that have a formula gray so that people know that you shouldn't type over this formula. At the end of a project like this, you can always protect the cells, but this is just the notation I like to keep everything very visible. And then now as we change our item, then it is doing a lookup in the table here. And you see here we have found a hit, but it's blank, so it's showing 0. So we can add some descriptions here. Make this a little wider. And then we can do the same thing, although I typed in gallons here for our previous video, we can make this a lookup also. In fact, I can even take this formula we have here. And it's the exact same thing. Only instead of returning our description, we want to return units and you see it even knows what columns are in here. So because we're using a name table, it knows what our columns are and it's trying to help us auto populate those. So here's our units. And if I come over here and we go to the spoon, which is the only one with different units. You see the units changes to pieces. And then in addition to units, the next thing we can do is the price, because we're not going to know the price or make it up as we add line. Instead, the price is something I forgot to put in here where we can just kind of, I think we're meant these numbers here and then half the price we'll look up also. And of course I'm completely making up numbers over here. We'll put some prices in here and we will do the exact same thing. We'll take our lookup, will get our price. And then instead of returning our units, you can see it now the texts that we had a price column that I just added. The same thing here. And then now we've really reduced the clerical work that the user needs to do to select an item so they don't need to know this information that's in the gray that is all getting looked up from our, essentially our database, which is just an another Excel tab right now. Then if somebody is maintaining this information correctly, then it's always going to pull the same information. So go back here. You have nella, we have chocolate and our information is updating as we go. So we'll pause the video here, and in the next video, we'll move on to updating our Add Item macro that is going to use this new information and add a new row. And we'll also have to deal with the line number count and make sure that we populate this to incremental line number as we add rows. 65. 3.3.4 Quote Tool - Finish Basic Add Line: Where we left off in the last video, we had created this lookup where when we populate our item here, that it looks up this extra supporting information so that we can add it to what we need for our new row of our lines table. Now we need to update our Add Item macro, which I believe this button isn't even attached to yet. So that it deals with these new pieces of information that we've now pulled for the item. So first thing we can do is let's right-click and assign this button to our macro of AD line item. Now if you remember where we left off, I'll click Add line item in here we have our new line, but we don't have information like our description and our line number. Yep. So let's deal with the easy 1 first, I'm going to delete a couple of lines here. Just so we can see the table easier. And we need to pull in our description, which we now have with this field here, and we haven't named it yet. So if we stick with our naming from before, we call it item description, and I'm just going to leave description short here. Grab that a new variable over here. We'll say description as a string. Put it over here. Description equals range, item description, that value. And then same thing we did for these other fields. We're going to place our description into the description column. So we have our column here, which comes from this column header. We're going to paste that there. And then description up here is what we placed into the value of that cell. Now we'll run this. Here we go. Now we have our description, which is again, looked up from our Data tab without needing to do anything when the user selects the item. Now the last thing we need to deal with is the line number. So let's say we have 234. We could make an assumption that the last line here is the highest number, but that's going to have problems later. For now, why don't we do that and then we'll deal with any problems later. So that is the easiest thing is we'll just look at the current lines here and make it look at the last number of the row at the bottom of the table, and then add one to it. Let's start with that. Let's come over here. We're going to figure out our line number here after we get all the easy stuff, which is here just pulled right from the user interface, will say line number as say it is a long, has a whole number again. So actually we need our table to be able to do it. So the code we're going to use, the Find, it is going to be down here because we need our table object already declared. So here we declare our table, which is here. And here we're adding our new row. So let's do it in-between here. So we have our table that we can work with, but we haven't added our new route yet. Let me move this down here just to keep everything together. We'll say latest line number as long. And let's figure out what the latest line number is first. That is on the last row of our table. So how can we get the last row of our table? Backup here actually? So if we have our table, which is Table lines, and we have our list of rows here. We can select our list of rows like this. So that range not select. I'm going to put a break here and hit F5. And then if I hit F8, you'll see this selected row one. And then if I place a two in here and hit F8, the selected row two. So this is row four here. But we need to put a number here, but we don't have to hardcode it. Instead, we can say cable lines that list and rose again. And instead we have a property called count, which is the number of rows that are in the table, is going to return the number of rows, which is four. And that is also going to be the last row, as we say, we want to return row four, which is the total count of rows. You can see here, as I drag this up and hit F8, we're selecting the last row, and that's going to work. Well, we have another row, say five rows next. That this is going to return that there are five rows and it will get us the fifth row. And then from here, right now, we're just selecting it. And instead, we can pull the first index here instead of the entire row. And if I come back up here again, I'll turn off this line break and hit F8. We're selecting the first cell of that last row. So if we combine this together, we can say our latest line number is the value of that cell, rather than just selecting it. And we could go even farther. I know of this line of code is getting really long and change this one to use the same thing we showed before where we're looking for the list column, index of the line number column. But I'll just leave it as one here. A lot of times I might only leave it for this one when it's the first column because it's so unlikely that this is going to be anything but the first column, we're not going to insert new cells here or new column here. That's going to push this over to the right anymore. Now we supposedly have our latest line here. So then our line number, we can even call it new line number. Let's see where break mode here, so I'll stop everything. So it's easier to edit our code. We'll call this new line number. And then here we'll put a new line number equals number of plus one. So I'll go ahead and try this out here. Let's hit F9, F5 here, accidentally hit F5. And so you see we added a new row here, but we haven't used this new number. So if I hit F8, here, we see our latest line number 0. I mess things up because I accidentally added this new row. This is one of our flaws with the system we're using here, although we're going to run with it for now until we improve it. But if this last row accidentally as blank, if things are latest line number is 0, rather than realizing there's a four here and this is supposed to be five and our new lines going to be six. So that's the problem I just accidentally created here. So if I'm here and I delete this row, I run this, I stop here and hit F8. And you see the latest line number is four. And our new line number is five. So I'm going to stop this now before we make any changes. And then we're going to add a new row. And then the one thing we're missing here is I come over here to our line number. And we're gonna make this. I'm just going to copy and paste it from here so you can see where it's coming from also from our column number on our spreadsheet. This is our line number, and then this is going to be the variable we created a new line on it. So I'll remove this break and we will run this in here. We get our latest number five. And we'll change this. And now we get our latest number six. So this will work for now. But as we saw already, in a situation I accidentally created this has a lot of holes in it that can cause problems. And we'll tune this up as we go through this project to make the lawn can't work better. 66. 3.3.5 Quote Tool - Delete Line - Refresh Count: At the end of our last video, we finished updating our add line button, which I'll just move over here. And we came up with what our next line number would be when we add a number. So we figured out that we get the incremental next number. And right away, I'm realizing that we're going to hit the problem right away as I even tried to begin to work with this lines table. So I think we're going to have to deal with this now that if I wanted to clean up this table and just make this data smaller, I'm going to delete these rows. And my lines are immediately out of sequence here. And so that's a problem. Now, I'd have to manually go in here and change these 212. Let me change the formatting here a little bit. And we'll move all this stuff over to the left. We just kinda clean this up a little bit. I'm going to change some numbers every year. That's not important, but it will drive me crazy if I don't fix it up a little bit, just a little bit OCD there. And we have this problem where the line numbers are only working when we have this perfect situation where we're adding a new line. And then as I need to adjust, my information is not changing. So let's deal with this. That I'm going to make a function that's going to delete the line also. So instead of just having a button, when we add an item, we want to create a user interface. So the user doesn't have to do what I've been doing, which is right-click the row and delete the row to get rid of it. Let's make it as part of what we're essentially mimicking here, which is a full application. And we'll build this right into our user interface. Just like we have. Add item will make a button called delete item. And we'll get into how to build this. And we can make this really user-friendly by just making it so that it'll delete the item that is selected. So we'll say delete selected item. And this is a really simple function. This button is going to just do this function of Right-click and deleting the row. But there's a lot of concepts that we'll build into here. So I think it's worth doing just from a training standpoint of seeing all the interesting concepts involved with making this simple function, or at least what is simple on the surface. So let's split this up again so we can see everything. And the way we're gonna do this is to delete our selected item here. So let's create a new subroutine to handle this. And that's what we're going to end up attaching to the button. So we're going to say delete selected item. We'll describe it as delete the selected row from line staple of the cell that is active. So if the person comes over here, let's say we have three items and we highlight this second row. We're going to click Delete selected item, and this is the row that's going to disappear. And then the problem we're solving here also is that we're going to recalculate our line numbers so that people don't have to manually delete that rows and then have this problem with our line numbers. So first thing we need to do is see what are selected cell is. So we can do that with active cell. If we say active cell that select, that's kind of redundant because the active cell is already selected. But let's say something else. Let's say debug active cell dot address. So let's do that instead. Let's assign this button to our new subroutine here and delete selected item. And when we click this, we should see our debug print says E6. And that is because we have cell E6 selected. So if I click over here, we have C 20, which is the cell we have selected. So that's how we can use this act of self, which end that's built into VBA. Imagine we can even do row here. So whenever you have a range, active cell is a range object. We also have our row property. So if I run this, you can see we're on Route 20. Now the easiest way to delete a row is if we're using our list object from my list row table. So let's actually declare our lists row object again, just like we did up here. And so now we have this list object to work on. So if we're on Route 20 here on the spreadsheet, we showed in our last video that we can actually do this and say list of rows to Dot select that range. And if we did something like this, this is our second row. But when we're using our active cell, we have our active rail being 20 on the spreadsheet itself. So we need to translate row 20 to becoming route to because we have this built-in function, but we want to get the number two out of it. In this case when we're on this route 20, something we could do is taking our active cell dot row and then subtracting difference. So if we subtract at 18 from here, for example, just using the info we've already gathered. This would be 20. You'd subtract 18, and then you'd be on row two. Then if you're on row 21 here on the spreadsheet, and then you subtract 18, you'd have three, and then you'd be on list row three. So it's basically just taking the difference between here to here. So you can translate your worksheet row to the list row of this actual table. So this is an okay idea, except for the fact that if we add any rows here, which we probably will through this project that's gonna push things around and then this won't work correctly anymore. So instead, we don't want to hard-code 18. This is a lot like our list column idea. We don't want to hard-code 18. Instead, we can get the row which is 18 here, which is how many rows are the difference between the start of our first row with this other function. So I'm going to comment this out really quick. And we can say table lines, dot. And our list object has a property that is called a header row rage. And then if I select this, you'll see that it knows what row are heterozygous. So we'll do the same thing here. If we have row, then that is going to return which row that range is on. So it finds our header of our table and then returns the rows. Can I press this? We have too much stuff in here, so I'll create this out and we have 18 over here. So what I've shown you is if I've replaced this 18 with something that's dynamically coming up with where the hetero is. Now we're doing that same concept of figuring out the offset between the spreadsheet and the list object row only it's dynamic. So if I hit F5 here, you can see that we are selecting this third row over here, and I can highlight the second row of our table. And it is now realizing that this is the list row object that I was on. Now, we're just selecting a row. I'm going to make this a little wider here. But instead, we can take this range now that we know that we're selecting the correct row and just say delete. So now if I'm over here and I click this, you can see it knew that was the row what we're selecting before. Instead we're running the delete command against it. We can add a new item here. And we can delete these rows. You see we still have our problem because we haven't addressed it yet. But at least now we're doing the deletion of a row through some code here. And that's gonna give us some control of what we can do as part of the procedure. Now what happens if we click up here and click Delete Selected? We hit an error here. And that's because as we do all this math, you'll see that there is no list row. It's gonna be something like 16 minus 18 is negative two. And then this won't make any sense anymore. So it's important for this function, the work that we are selecting a cell within this table range. We want to be careful here because we're deleting stuff. Anytime we're deleting things, we can accidentally mess up our spreadsheet. But I know that even if we click in this header, it's not going to work because that's going to be 18 minus 18 equals 0. And so there is no list of row 0. So we'll stop here. So before we tried to delete a row, Let's error check for this. We need to make sure that the cell that we have selected even below here, it won't work. We need to make sure that the cell we have selected is within this range. Over here. It's specifically within the data of the table. So our list object again, in addition to having our hetero range, we have our data body range. And I'm just going to use select again so that you can see what's going on. I'm going to create a breakpoint, hit F5 and an F faith run, just this line and you see it's selected that hold data body range. If I come up here and hit F8, it knows where the data of our table is. Now we need a function that is going to figure out whether or not our active cell is within here. So I actually know this function, but you could go to Google for example. And I would type in something like VBA. Herman, if active cell is within certain range or something like that. And you should get the result for the command here that I'm going to use. It's a bit of a non-intuitive command. So we're going to say, if not, intersect active cell comma and our range, which is Table lines that David body with age. Nothing. So actually, I don't want to say no. I actually, I'm going to remove that intersect is nothing than cell body of the lungs. So this basically returns a value. It returns a range if this range and this other parameter range are overlapping. So if there's an overlap, this will return the range that is overlapping is nothing, is saying that the returns nothing. So if This function that is finding the overlap returns nothing, then that means there is no overlap. So if there is no overlap, Let's send a message box. The user saying active cell is not in the table data. Select cell. And then what we need to do is stop because we'll actually for now, we're just going to leave this. We don't want this line to run if we hit the situation. So instead we're going to say else. A few different ways to do this. Another way I might do it is just end the whole process here if we hit this situation. But instead, I'm just gonna do it in house here. So if we're not overlapping, it sends this message. Then if we are overlapping, then we can continue and run our delete command. You see if I'm outside of here, I can't execute them break modes, I'm going to stop so we can start over here. Active cell is not in the table data. Please select the cell. Now if we come back here again, now it's working. And now the part that originally made us create this function is we need to handle these rows here. So whenever we delete a row, we should reevaluate what our lines are. So let's create some code here, re-evaluate line numbers. So we could try to look at this and figure this out. But instead I think the thing to do is to just clear out our line numbers and replace them, and we'll just create them from scratch. It's a pretty simple thing to count, just one and upwards. So let's do that. Let's loop through our rows. So we're gonna say for I equals 12 and then our number of rows, lines, thoughtless rows. Now, we're going to use our table property. We haven't declared IN variable. So we're going to say I as long i. So we've created this loop that's going to loop through one to the number of rows. There are just two. In this case. We're going to say Table lines, this rows. And then again this is the row in the table. And we can use our counter ion. So it's going to be one and then row two and then row three. And then we'll say range. So the first thing of the range is always gonna be the line number all the way on the left because it's the first cell in the row. That value equals I. So I is gonna go 123 and then it's going to label the rows. So let's run this. In fact, I'm going to separate this out into a separate subroutine, which we had in our earlier videos that we can call a subroutine from another subroutine. Let's say Refresh line numbers, will create a new subroutine there. We're just going to take this entire thing here, cut and paste. The only catch here is that our table lines list object isn't declared. So we have to declare it again in this separate sub routine. And so let's run this again. And now we can run this refreshing the line numbers without running the deletion of a line. So you see it just recalculated this here. Hit this again. If I add another line here, 123, that's working. If I clear this all out, then we are refreshing our line numbers. And then when we delete a selected item, we still have this problem here. But then we can call this separate subroutine, which is going to refresh the line numbers at the very end of our deletion process. So we can add a line item. Here is something interesting, I'm just realizing is we messed up our lines. We added a line is going, hey, most recent one is three, so your next one must be four. So something we can do is since we made this a subroutine, good thing we did. We can reuse this yet again, even when we're adding a line item. So here's our add line item. And at the very end, Let's refresh the numbers again just to make sure they're correct, since this is a very small bit of code to run. Now when I add a line item, it even re-evaluated everything, even if we mess something up manually and it is recalculate our line numbers so that they are correct. Then if I want to go to delete some lines, then I can select these. And it is re-calculating each time. And you'll see here, even if we add vanilla as our fourth row, we're going to delete this and you can actually see that this is the row being deleted. But the line numbers are now correct again. Okay. One last thing I want to show you as I was reviewing the recording earlier in this video, is that another way that would have been simpler? Back at the beginning of the video, you might have thought, why don't we just right-click and delete the row? In which case we would avoid all of that logic that we needed to do to determine the specific list row object of the table when we could delete the entire row of the spreadsheet like this. Instead of going in the list rough specifically in the leading 0 here. This is another magical part about the named table that we have here, or the list row object is that when we work with the list row or the list object, it's specifically knows that we're talking about this row. And that's something you can do, is have this separation between even this same exact row here, where if we delete this on a spreadsheet, of course this is going to go away. But meanwhile, if we work with the list object of this table in the list row, specifically, excel is really good with being able to figure out that we are only working with our data within this range rather than working with either the rows or columns of the entire spreadsheet. So that's one of the reasons that we're working with our list object and our name table is because Excel is doing a really good job realizing that this specifically is our data over here. And we don't want to go out of our way to affect things that are outside of it. So that's it. I just wanted to add this in at the end of the video as a further explanation. There. 67. 3.4.1 Quote Tool - Excel Output Template: Okay, Now that we've finished up our functions where we can create our quote and we can add lines, and we can delete selected lines and set up the basic information for our quote here. Let's move on to some real automation. I'm sure we're missing a bunch of details here, but we'll add that later. Let's go ahead and get into our step where we add a new button that is going to create our actual quote cancel here because we don't have a macro yet. I'll add this new button, will say create. There's a bunch of different ways we can make a quote. But just for starters, because we're doing mostly automation in Excel right now, let's make our quote form as another Excel file will have the option later to update this and make it a Microsoft Word file or PDF and all these different ways that we can automatically generate documents. But to build on what we've gone over so far, we'll make our quote output in Excel file for now. Let's set up this quote so we need a customer here. We'll say ice ice cream wholesale ink as our customer name. And our contact name will be something. We can do. A quick name here. And let's grab clay O'Neill here. So our contact name will be clay on Neil at ice cream wholesale think now there's a couple of ways that we could do this, even though we've chosen to make our output template in Excel or output quote, can either be generated from a completely from scratch Excel file. So we could create a new workbook here and create a new quote template here, completely from scratch and have our code build what a quote might look at, might look like. So it will start to say here and actually type stuff and we'd have to rearrange all of our cells and everything. Another way we could do this is not have the code make a lot of details, but instead we'll set up a quote form as a standalone Excel file, and then we'll open that up and essentially fill in the blanks. So the information we have from our quote here, the only stuff that changes is basically our content at our header and then our lines. And so we can make a whole template that looks a certain way already in this saved Excel file. And our Macros just going to open up the template and then put the information in the right place. To start. That second option sounds a lot easier. So let's go ahead and start to build that idea. So I'm actually going to close this. We'll come over to our quote files here. This is where our main Excel file is. And maybe I'll just put it over here in this folder and we will create a new Excel file. And we'll call that. I'll use an underscore here just to avoid a space. We'll open this up. And this is a brand new blank Excel file. And we'll make this our quote template. I'm not going to make a very good one because that's not necessarily the idea of these tutorials. So I'm going to make a pretty crude one here. Let's say quotation will make this kind of similarity here. We'll say, maybe we'll put our quote number here. We'll say customer contact. And then we'll have some information over here about our quote will make ourselves style over here, we'll format this as a table. Why don't we go with green, I guess maybe we'll go with a green theme here. If our grid lines in your quote number can go over here, instead, make this font a little bit bigger here, create some borders over here. I'm here. Okay, well, just start with this for now. I'll save this template and we need to set this template up so that it is relatively easy for us to put information in these areas. So same concept I've talked about plenty of times here. We don't want to just place it in cell B3, although we could, we can even on this output template, create named ranges so that we can work with these fields more easily to your customer Contact. And we'll name this table. Table lines were actually reusing his name table lines. I don't know if that's a great idea, but it's actually a different file completely. So you'll see how we can get away with having the same name and we'll work with that. Despite being a name that we used in our other Excel file, it might be a better idea to say table output lines, but we'll leave it like this and you'll see how that's dealt with in the code later. And up here is a field also. And we'll make this number. Okay, let's run with this for now. 68. 3.4.2 Quote Tool - Excel Output Header Transfer: Okay, let's run with this for now. I'll save this. And now we have this cool button over here. Let's go over to our code. And we'll split our code up over here as we usually do. And we have this button click F5. I think this was generated when I created the button. Let's actually make this a different subroutine name. And we'll call this Generate. And we'll change this module one Name. Generate Documents. Again, just to bend everything together in a descriptive way to generate actionable, say with Excel. Okay, so we have our separate Excel file that we just created as a template over here. And so we need to open up that file to start. So let's set a workbook object that's going to stand for this Excel file that we opened up. Because then we're going to have to interact with this workbook. We're going to say workbook, quote as this workbook object. So this is actually a object variable for an Excel workbook, essentially an Excel file. And we're going to say set wb equals. And then we're going to open a workload, which I think it's workbooks. You can actually see I'll pick control space here. And it added an S automatically because that's the only keyword, will say open. And then we need the path of our quote template over here. So let's go ahead and create that dimension as string. What this needs to be the full path of our quote. What that means is here, our folder path. And then backslash, our file name over here. And I'll add this file name over here. And this is the full path of that file. An easier way to get that. There's Windows 11 here. You can use copy as path. And this is also the full path. So that really just put the same thing over there, but that's a quicker way to get the full path of any Excel file when you're navigating in your File Explorer. So now the workbook we're going to open is our quote template. And then as we open it, we are going to set this WB quote as the workbook that we're opening. And we can go ahead and try this out. Let's hit Play. And you see our template just opened up over here. As an example, we can say WB, quote close, since this object stands for our file, and you can see if I hit F9, so we stop here, I'll hit F5. So this runs and this is open now. And then if I hit F8 and run this closed line, that workbook closes. So you see now we have this workbook object, which is going to be that file and we can work with it. Now before we close that workshop, we wanted to do something with it. We want to move all this information over. And actually we don't even want to close the workbook, so let's comment that out for now. I don't know if we'll use that later, but we'll get there. Now, let's go ahead and run this. And we have this workbook open. And now we can think about the information we need to populate here. So we see we have our quote number, we have our customer and contact name. So let's start with that. Basically the three pieces of information right up there, let's say number as String, customer, as gray, and contact. So let's fetch this stuff from our user interface. Over here on the left is the value of our range. Quote number. Over here. We have these two cells which we haven't given names yet. So we can come up here and call that customer name. And we'll say contacting. Good old clay O'Neill over here. And we'll have a customer equals range. Customer name dot value, and our contact name equals rein, contact the value. One thing I mentioned here is I'm just calling this range out. But something that can get a little bit confusing. And I think we're okay for now, but it can certainly get the program itself mixed up is that we have two workbooks. And so when I say something like range, Quote number, we're going to see the same problem with our table name. We have Quote number over here, but we also have Quote number over here. Also. It can be easy for us and even the program to get confused as to which range we're talking about. Now that we have two workbooks, especially when they have named ranges that are overlapping. In this case, our code exists inside this quote, greater Excel file over here on the left. And so I think it's going to know where to get the information. I can go ahead and create a break point and run this just to test it. If I hit F8. Actually, I was wrong there you see it doesn't know. You see this quote number is blank. That is because it is defaulting to the file that is active. In the active file in this case is the last one we've worked with, meaning we opened this file. This file is the thing that it's looking at. And now it's getting the quote number value, which is blank from this file. So we're seeing a problem directly about how the code is getting confused as to the named ranges. And with that logic, this file is what we're looking at. And it's not even going to know what the customer name ranges because there is no range by that name in this file. So if I hit F a, we have an error. Meanwhile, if I just activate this original Excel file where we do have customer name, you see we no longer have a problem. The term for this is that we're not being explicit in our use of these calls over here, meaning we're not stating the details. So this thing is trying to guess what we mean and running into errors. So to clarify that we're not working with named ranges by these names in our quote template. We're going to write this work, which is just another workbook object, but it means the Excel file that this code lives in. This is explicitly going to tell it that when we use these names ranges, we mean in this workbook. So let's go ahead and do that for each of these. So there's no confusion. So let's not, let's run this again. We actually have this problem that the workbook is just a workbook level, the file level, and the workbooks don't actually have ranges in them. Instead the workbooks have worksheets and then the worksheets have ranges in them. So I have to clarify, that actually mean this main sheet inside our workbook. So I can add this to that. We've added this. Now we're very explicitly telling the code where our ranges are. So we hit another area here where I forgot to put in the S. It's sheets, not cheap singular. So let's try this again. Maybe I'll get it right. And then we hit F8. Then we hover over these, we can see quote numbers to customer and contact name. And we're getting the information correctly. And now you can put a comment here. Information. And now we can use this explicit reference where we tell it specifically which workbook we're in, which is WB quote that we set up here. When we open the template, we say sheets. We can say Sheet one here. Or we could say one, which means the first sheet, which is the only sheet in this template, will just change this tap, say quote. That's the easier way. And that way, again, we're not using these generic names. So we're gonna say is quote that range. And then on our quote template, the range is also Quote number, value equals quote number. Let's just test this one to make sure it works. Now, if I FAA, that's even step through this, we open up our file, WB quote sheet, quote, and then I'll quote number value. We'll run this and you see it placed our number over here. Will change how this looks a little bit. I'll do a Control X to cut and paste over here. And then the nice part about named ranges, as you see are named reference moved along with our cut and paste. And then I can right-click and pay special formatting just to match the formatting over here. So I'll clear this out. I'll hit Save and let's finish this up. Stop our run mode. And we'll repeat the same process for Quote number and then two customer to contract. And then here we want our customer, which we can copy and paste and contact name. This set over here. Now when we run this, you see this information travels onto our quote template. And we'll make this format and change a little bit here. I'll just change this formatting over here to the left. 69. 3.4.3 Quote Tool - Excel Output Lines Transfer: Now we need to populate our lines. As we compare these, we can see that our information and our two tables comparatively is basically the same description, quantity, unit price. So I forgotten a column here. We can do an insert columns to the left, and we'll say units, unit price and line total. So very similar thing here. In fact, just for practice, let me remove this units that I've just added. We're going to delete this column. And for quantity will combine this together just to see how things don't have to be exactly the same. We can do some processing as we move stuff over, so we can add our units directly to our quantity. I'll just show you that they don't have to be a one-to-one, that we can manipulate the data as we add it over here. Now that we've moved this data over, let's make another section and we'll say line and for now, we'll create objects that stand for our source table. And then we'll make another one that stands for our output over here. I'm going to call them the source of our information and our destination, which is where the information is going to land. So how I can do that is I'm going to create these lists objects that we've worked with before. And I'm going to call it table lines, source, list object. And then Table lines destination. Now the set them, I'm going to say set cable lines source. If you remember. These names, tables in our Excel files have the same name. But we can do something like say, this workbook that she made. Then just like before, we can say our list objects and by name is cable lines. Meanwhile, we're going to set our table lines destination equals not this workbook is going to be WB quote sheets. So you see, even though we have our same table names here, because we're working in two files. We can be very explicit in which files were working with so that the code knows which one is which. And now in our code we have two different tables. One that's the source and then one that is the destination. So we're going to move all the information from this source table into our destination table. So we're going to have to loop through every row in our source table. So let's go ahead and do that. For I equals one to Table lines, source dot count. Now to make things easier, we're going to work one row at a time. So let's create objects even for the rows. So in the same way that we did the tables will do L rho, which is our list row for our source information as list route and we'll say L route, destination of this row also. You'll see how we use that over here. As we set our source, as we loop through each table, we're gonna say L rho. So our source row, as we go through each row is going to be table lines source that list the rows. So as we go through row one, we have our source row. We're going to look at this. And then our destination row is gonna be this first row over here. And then as we look at row two here, we're gonna create a new row over here. It's something I showed you before, is Excel is smart enough that as I add new rows of this table, is going to know the push this text down. So even if we have one line or a 100 lines, it's going to know that push all the information downward as we work with this table over here. So as we look through here, we're going to set our row. And then we're going to create a new row. Set L rho destination equals cable lines destination, that list goes down, which is something we use when we were creating the ad line fund can the Add Item function for this table. And how we can line this up. Actually, I'm going to create some extra variables here just to make things more clear. There's gonna be more code, but it'll make what's happening more clear is we're going to create all of these variables. Line number is a string, item as string. In fact, since it's just an output, will just make everything strings to keep it simple. I know that the sum of these are numbers, but we'll just make them all strings for now. See if we can simplify things that way. As keyword over here, I can say quantity as ring, unit, price and extended price. So let's set all of these. Now that we have our source row of information, we want to take this information and place it into our variables. So let's say my number equals Here's our row here. Row source. We could say 12345 as we've gone over a few times now, we don't actually want to use our numbers in case our columns change. So we're going to use this method where we have our cable lines source. We're going to find out the index of our list column when you supply the list column name. So that if these indexes for our columns move around and we insert or delete columns that will figure this out dynamically on the fly. And so we're going to say line number index, which is essentially saying one. We're going to get that index value of our row. So this is going to return one. So it's essentially the first cell of our row. And then as we type in this next one, it'll be more clear that we're saying item equals, and we can take this entire row of information and change this to be our column header over here line, sorry, our column header item. And this is going to return to for being our second column. And we'll get the second column of that row. And we'll keep copying this over. In fact, I'll copy this line over here. And we'll say description quantity units, price and extended price. Description quantity units, price, extended price. And we have to update our column. So our description comes from our column header of description. I'm just going to keep moving the information with copying and pasting like this. Even though it might be easy to type, it's going to make it clear to you where I'm getting these values from. Units comes from this header. Price header goes into the unit price variable. And then our extended price is this forward extended, goes into our equity price variable name. And now we have everything for this row in these variables. And we've added this new row to our destination table, should be able to look at this over here. And then for our destination table, we're going to do essentially the opposite. Just like we're getting information from a cell in the row over here. We're actually going to put information in our L rho destination. We have our range, we have our column name called line number. Then we're going to set this value. All of this code basically means this cell over here. And we're going to set that we are in line number that we got from our source up here. And then we do the same thing for our item description. Quantity units, which actually won't be units because we combine those two fields together, unit price and extended price. And we actually have one less column in this output because we combined quantity in units together where we're planning to do that. So let's copy this over here, which is item I'm just going to type this out. I'm getting this from these column headers, but without messing around with all my window sizes, will say description, quantity, unit price. And price. We use the word line price here instead of extended price. Oh, actually we use line total price. And then it looks like I accidentally moved over an extra row. So over here we have 1234567 lines. And then over here, since we combine them, we have six months. So this looks about right. And then on our output we have line number here. We have item over here. Description as our variable quantity. Now this is where we are combining our quantity in units. So we're going to say quantity and an empty space. And then we're gonna put our units and you'll see how that will come together into a combined string. And then we have our unit price over here. And then we have our extended price over here. So there's a lot of code here, but I think there's a little bit more clear what's happening. Even though it took us longer, we were getting all the info from our source row and then putting it into our new destination row. And then this is going to loop through all the rows. Let's actually run through this. So this is the best I can do over here. Let's try to run this and I'll use F8 so they can work our way through this line by line. So we opened our file, we've set our table references, source and destination. And immediately we run into an issue with looping through our rows here. And that's because I have this count parameter, but I forgot to write that. What we are counting is our list rows dot count. So I just forgot the list Rosenberg here. I'll continue saying F8. Now we have our row over here. We're getting our number one over here, our line items. So now we're getting the info from this one row. Now we added a new row of information over here. We actually had one blank row over here. The clear that out. And we're adding the information into this grid. Now, it's saying we have a problem with this row of information. Let's check our line total price over here. And our problem here is that it's saying that we don't have a column called line total price, even though we see one over here. And that's because over here we're working with our destination table. And I forgot to change this to our destination table. So it's looking for a column called Line Total price in our source table. So there's a lot of little details to get mixed up on here. Let's go ahead and fix all of this up. So I'll actually take this whole word so I can double-click in and update all of these to be talking about our destination table. So I'm going to make this bigger. Something we forgot to do as we come over here is there was already a blank row. So before we do this, we need to clear out this table completely. So we want to ensure this table has no info in it. I'll go ahead and delete all of these rows over here. The kind of strange thing about these tables is even when there's no rows, it looks like there's one row. So you can't actually visually see the difference between a table with one row and 0 rows. Anyways, let's go back over here. Let's run this step through our code. Now you see that information is showing up over here. You see here we've, we've successfully combine the information together so that our quantity in units are together, in our unit price is showing up blank. And I'm not sure why that is. And you see it's that there's no units price here. I think it's unit price. Yeah, I accidentally had a s there. And so if I come up here and I click this, now, it was just a typo in the variable. Unit price wasn't populated correctly. And then now we should be looping through to the next row is getting from our source. Then now it's putting this information into our destination table with another row. You see the main difference here is we're on line two and we have ten gallons instead of five, which we can double-check over here on our source that we're at ten gallons. I'm going to hit play just to run this all the way through. And you see now that we have all of our information from our source table, moved over here to our destination table. 70. 3.4.4 Quote Tool - Excel Output Save File: Now that we have this, and now we've essentially populate our template. This is a very simple quote. There would be more than this on a normal quote, but we'll just use this for the demo. And what we need to do is just save this file as our output. Let's say WB quote. And we can say Save As because we don't want to save this over top of our template. We took our template which should start as blank, and we're going to save this as a new name. So where we can save this, we actually created a quote folder. So in this case we're working on quote number two. We should probably save our quote in this folder for quote to. Instead of having to deal with all of this from scratch. Remember that we created this tool that's going to construct a path of our quote folder. So we have our folder path, which is the folder where all the quote folders are in. Then we have this logic over here, actually including our quote number, to get our quote number. Then to construct our sub folder name and create our new folder full path. So let's actually copy that. And I did a Control C there will come back over here to generate docs. And we need to create our new variable. So we'll say save to respective. I'm going to paste this over here. We're getting our quote number, which we actually already have, so we don't need that anymore. We have our folder path, which is right here. We have our new folder name. So actually called. Recall, her name is update this variable, we have to work quote. We have our quote number pushed into six digit format and we append those together. And then our full path is our folder path plus our quote folder name. And we can call this our folder full path. Now we have a folder full path. We can see that the save as function takes in our filename, which will be our quote folder full path. One more thing we're missing is our filename. So this is actually just a folder path. We haven't come up with our new file name. We're going to save this as will actually change this to a file full path. Let's add in our quote filename here, and we'll call it quote. We'll call this actually, let's reuse our folder name, which is going to be two with six digits here. And we'll call it a folder named output dot XLSX, since this is an Excel file. So that was a lot that we've done here without checking. Let's see if this works. The last thing I need to update this file full path, this quote fire full path to be what we're saving as instead of the folder full path, which is the variable we changed. This was a lot. So if you're following along, you can step through this code line by line. Lets clear our template out, delete our rows, and will delete all of our content over here. And let's see if we happen to make this work on this first try here. And before we do that, let's open up the quote template. Just to confirm that this quote template is blank right now, we'll close it. Come over here to our code. And actually one more thing will add here is a message box that says file has been saved. We'll do another vb line feed. And let's output our full file path over here to our user. So it confirms that we successfully saved the file if this works correctly. So I'll go ahead and we'll press Save here, where we'll hit play rather. You see this is all populating. File has been saved at this path over here. It's all looking good so far. And if we go over to our quote to subfolder, here, we have our output file. If we open it up, just found was actually already open. So let's close it. Basically never closed after regenerated it. So now we open it up. We see that we have our quotation here. If we come back over here to our template, we see that it's still blank. Let's actually create a quote number three over here. Let's delete one of these lines and we'll add another line over here. Let's add some strawberry, shake it up a little bit. We'll add another line item. And let's create our quote over here. We actually never attached this button to the subroutine that we create it. So let's attach it to create. Generate quote is our subroutine. We'll click that template pops up. We actually have an issue over here for Save As. And I'm immediately realizing why we have a saving issue over here for quote three. So let's close this over here. That is because it's going to try to save in the quote three folder, but we don't have a quote three folder yet. So let's open this template up. It's still blank. We need to hit Create folder. So now we actually have a quote three folder. Now that we have a quote three folder, let's create our quote. This info got populated file has been saved. Here we are with our quote three folder, double-click it, and there is our output file. We saw one small issue there, which is if we go to four, then we didn't have a folder in it, tried to save and ran into an error. So let's close this up really quick. Let's go to our subroutine for generating the quote. Before we even generate the quote error. Check for that just to make sure that we have a quote folder. Let's see. So we need to check for that folder with all of this information over here. So let's actually bring this stuff up to the top because we want to do it before we even start degenerating the quote, because we don't want to make the file and then not be able to save it. So let's go over here, quote file, full path. We actually want a stepping stone where we'd have just our quote folder because that's what we want to check for. We want to see if this folder exists. So if we do four, we want to basically check if four exists. So let's separate this out. We'll say folder, full path, string. Folder, full path is just this without our filename at the end. So it's essentially this. And then our quote file, full path, hands are filename. So now we use our quote folder for math. And then we append our file name over here. And we didn't need this extra ampersand. So if you follow along to what we just did, we basically just split this into two steps. So we have another variable that holds our folder full path before we construct the full thing that is going to output our full path with our filename. Just to show you, this is a bit confusing, especially with all these long variable names I created. Let's just output these. So here's the output for the folder. Here's the output for the file. Let's step through this line by line. Is saying we have a duplicate declaration here. That's because I'm using the quote number variable a pop, and I haven't declared it yet. So let's say Quote number as string up here. We'll step through. Here's our quote folder. This is saying our quote number is 0. So why is that? That is because we get our quote number right here, which is down below all this code where we're using it. So again, we have to move this stuff outbreak, so we're rearranging. So now we get our quote number first thing so that we construct our paths first. Let's kinda able to construct file folder saving. Open to it. I can start to populate data. I know this is getting a bit confusing, but we're going to make sure that we have our sequence correct here. Now, let's stop. We'll hit F8 again and step through. Now our quote numbers, actually something. And then when we construct our folder full path, Let's clear this out. Here is our folder path. Here's our file path here with our filename there. And then the reason we created this is so that we can use something that we used in our create an Open Folder sub-routine where we're going to say if directory folder path, whole path actually db directory equals blank, then sub folder does not exist. Now let's throw our error message. Generate. The file does not exist. Error will occur. Even at process will be canceled. Then we're just going to use this end keyword, which is just going to stop the entire macro in its tracks when it hits this line is going to stop everything and not continue downward. So in theory, we have this all figured out. We've rearranged things where we're figuring out all the folder names and file names up top so that we can check to make sure the subfolder exists before we continue forward. And if everything works there, we're going to go through everything of opening a template, populating the information, and then saving our file. So we have a pretty built up subroutine over here. You can see our tool is getting pretty intelligent and complicated. Along with that, Let's create quote, actually will step up to four, where we do not have a sub folder yet. So let's make sure that we are catching this situation. We hit Create quote, cannot generate file, sub folder does not exist. Let's make this even better. Cannot generate file some folder does not exist. Let's say the following subfolder does not exist. We'll put a colon here, put a line feed, we'll put in what we're checking for, which is a float folder full path here. We're going to use this underscore character space. Underscore will let us continue over to the next line. And this makes the second line of continuation of this same line of code over here. That's what this underscore character will do, is tell you to continue on the next line. We're going to say ampersand and another line feed will say process will be cancelled. So let's see how this looks. And we'll see how this looks. I'm actually going to create two line feeds here. So you'll see the gap when we run this. Now if I say create quote, the following folder doesn't exist. It tells us the folder that it's looking for. And then it says process will be cancelled. And this is why we have two spaces here. Now. We create our quote for folder. Now we can create our quote runs. This template file has been saved. In here. We see quote for has an output. Then the final touch we can put on this is closed this file. So since we're saving the file while we go ahead and close it, so it doesn't need to be left open. And now we'll emphasize one more time. We'll say five. Create the quote. The folder doesn't exist. Let's create the folder. Create the quote. Five here. Just tells us the file has been saved. It closes. Then here's our output Excel file for quote five. 71. 3.5 Quote Tool - Auto Outlook Email: Now where we're leaving off is that we have this button where we can click Create quote, and it's going to open up our Excel template and generate a quote output as a separate Excel file and then save it into its respective quote folder. We want to move on to our next step. So now that you generated in Excel quote, we typically are going to want to send that to somebody. We want to send it back to the person who've requested our quote for our store here. So I'm going to create a new button over here. I cancel so that we don't have to select the macro and say create new map. So let's use that. Let's hop over to our code over here, we'll open up our VBA editor and let's see, we have Generate Documents file management. We'll just put it in generate documents. So let's put this together with our code before just sharing the same module here. So we don't have too many modules and we'll say sub generate email. Then pin this over here, and we have our general e-mail button over here. Let's attach our generate e-mail button to our generate emails subroutine we just created, which doesn't have any code right now. I'm just gonna put a message box that says about to generate email. I click my button and we say about the generate e-mail. So now we're ready to write some code in here from an earlier lesson for intro topics, we went over adding a reference library. So we're going to make this pop-up and Microsoft Outlook. So we're going to go up to Tools here, references. And we want to add our object library so that we can control Microsoft Outlook. So if I scroll down here to Microsoft in alphabetical order. So we're looking for Microsoft Outlook. Here. We see our outlook 16 object library, that is the latest one and the only one in this case, if there's more than one, I always choose the highest number. So our outlook 16 object library, we check it and click, Okay, it's going to reset our project because I was in run mode. So that's okay. Then if I come over here and I'm going to create an Outlook message. So we want to do the equivalent of creating a new email in Microsoft Outlook. I'm gonna say dimension O L for Outlook. And I'll say message is the name of our object variable that I'm grading. It will say outlook. And this only exists because we added that object library where I went to Tools and references. But since we did that, we have this outlook object. And then in our outlook object library, we can say Outlook Mail item. Male item is a message. Now that we've declared our Outlook message, we need to set it as an actual Outlook message. As we always do with object variables, we declare it and then we need to set it as an object. We'll say O L, O L message equals Outlook application dot create item. We're going to create an Outlook Mail item. So this is declaring our variable type. And then now we are setting our new variable as a new message item. So this is kinda similar, reminds me if you do a new workbook object, then you say dimension Workbook, Workbook, and then you say set workbook equals workbooks that add. This that we've seen before. This is the equivalent of workbooks not add. This is creating a new outlook message, but at the same time, setting it to the Outlook item object that we've created so that we can work with it. So I remove this. And just to show this, we can say Outlook message dot display, and we'll do this to start. I'm gonna go ahead and remove this message box because we'll see that a bunch of times as we test this. Okay, now we'll test this out. So I hit F8, we create our message object and we run the display line and you see an email automatically pops up over here. So it was that simple. We now have a button that when you click Create email, it automatically pops up Outlook and creates a message here for you. Now that's not saving us too much time yet. So let's add some more functions to this. So we have our display message and we can start to type some things like object message. That subject equals is the subject. We can say, oh, well message that body equals. What we should actually do here is use a width statement because you can already tell that we're gonna be calling our object a bunch of different times. So we're going to go into save that repetition here by wrapping this in a width statement. And then we don't have to write a message over and over again. So our body is kept here. And we'll just start with this. Now, if I hit play here, you can see it was that easy. Now, we are sending our email here, our subject line tax in our body text. Into these properties about the email. So since we are doing something with our quote here, we can start to frame this out where we're going to say our quote number as string. As we've done in the previous videos. We'll say our quote number is a quote number named range. And then we can say Quote number. And we'll say probe now here as our subject and in our body we might say something like here is quote, unquote number your requests for, thank you for your interests. So we create our message there. Have some error here. I'm probably messing up, yep, ampersands and quotation marks. Usually when I'm combining strings like this, we run this with F5 and we see now we're creating a real automated e-mail here. And just like our quote template, we're keeping this pretty crude. The goal of this class isn't to show you how to write good emails, but to automate this e-mail process. Now the main thing we're missing is that we are missing our attachments. So how we can add attachments is the same thing. We can say. Attachments. Remember this is the same as typing OL message dot attachments, that ad. And then our source is our file path. So we're going to leave that blank for now. We'll come up here and we'll create a new variable called attachment as string. We'll have attachment path equals something over here. Now we go over to our quote files. Let's say we were in quote folder five here. And if you remember, I showed you the shortcut. If you right-click and say copy as path in Windows 11, then we have the full path of that file. And we can say our attachment path is this, and it includes the quotation marks when we use that Windows function. So this is the path of our file for quote five, I just chose a random one right now. And of course we're going to have to make that adjustable. But now we can take our attachment path, pass it as a parameter into our add attachments command. And let's hit F5 to try this. Out. There we go. We have a quote file attached to our email here. Now the issue is if we were sending quote for we don't want to have quote five hardcoded over here. So now we need to construct this dynamically. And then if we do that, then we can replace that variable in these two places. So let's go ahead and do that. Well, we call it we'll call it full name. And our quote, full name notation is quote. And as you may remember from before it, we're going to take our number format. I'm going to take our quote number, enforce it in the sixth digit format here. So this should be our quote, full name. And we're going to take that and replace these two spots with it. Ampersand. This is always a bit of a brain teaser here to just work with these combined strings here and make sure we get our sequence right. But I think I just got it right there. Of course, will have an error if it doesn't work. So we can always come back and fix it and we'll run this. And now Quote number four. And we've attached coat number four over here because our file path for our attachment has changed. Here's our quote is quote for that we generated from our previous video. And we have this as a create e-mail button. And you see this automatically pops up. Over here. You see we don't have an automated e-mail of who has send it to, so you can return it to the person by typing their name automatically. The nice part about popping this up in Outlook is it's going to show up in your sent e-mail box and you're using all these features that are built into Outlook. So you can kind of pick up where this macro left off and add people to CC. It knows your address book and everything like that afterwards, rather than having to code all of that into your macro. But what we're missing here is a contact e-mail. So let's say we put our contact e-mail and here I'm just copying and pasting this format here. We had play at IC W.com here. Now we can name this cell as contact e-mail. And then we can come over here to our code again. We'll create a new variable here for contact e-mail as spring will pull our contact e-mail as our range of that email that we just named. And then I'll put it in the order that we generally send or type up our emails in two equals an email. And I'll clean this up really quick. And so now if we come back here and hit Create email, we even have our e-mail address over here. That's it. That's a basic e-mail for now. We can add a lot of different functions here. There's different ways that we can make this a very customized e-mail with tables and all the information that you would ever want in an e-mail body. And we can control all that automatically too. But here's just a basic proof of concept. 72. 3.6 Quote Tool - Customer Lookup Table: So in our last video where we left off was that we create this function where we have a e-mail button. When we click it, it automatically generated this email with the subject body text and the attachment of the generated Excel output file. And we automated our contact e-mail address from our contact e-mail over here to good old clay on Neil. This video is going to have much automation in it. We're just gonna do a quick touch-up of this tool where we're going to do the same thing for the customers that we did for items over here. So right now we're set up where we need the NR contact name. And we took that from a random name generator and our contact e-mail, which we also made up. Of course we're going to continue making up information. But what we could do is similar to our items. We can make a little DataTable of our customers. Customer information here, it will say customer name. We can say contact name. And we're making the assumption here for now that there's one contact per customer will say contact e-mail will turn this into a table. So Control T. Again, my table has headers. We can take this information, this our first-line clay on Neil here. We have clay at ice cream wholesale.com. I CW. I'm sure this is probably a real website or something like that. So sorry, if this is u. And now add a couple of extra lines here. So this will be the fun part. And so we'll have our Customer Name be Connie's cones, LLC and our contact name, I guess it needs to be Connie. We'll leave that blank for now. We'll go back to work random name generator and a little bit at another one here. It'll be ice cream. And then we need some contact names. So let's go over to our trusty name generator over here is the one we used before. We'll grab a name over here. So let's see. We got Clarissa Vargas and we'll say Connie Mack drums. Connie at CCl.com. Again, sorry if I'm taking your website name here and marissa at ICR view.com. Alright, now we have our customer information. We can do the same thing we did for our items over here, which is that we just used a VLookup formula. So over here at our contact name. Actually, before we do that, we'll come up to our customer and I forgot to give this table and name. So we're going to have to make our customer name a drop-down. So we'll say table customers over here. If you remember from before we made this a data validation, went to list and then we can say indirect and actually use our names. So cable customers. And then over here in our brackets, I'm being careful not to use our arrow keys here because in this specific formula bar, using our arrow keys left or right is accidentally going to choose all these ranges. In fact, I'll do it just as a reminder of what will happen is instead of moving our cursor over, it starts to select cells. So click in here and we write our column name, which is customer name. I believe. If it's wrong, it'll throw an error, which it isn't. So now we have our dropdown. And then for our supporting information like contact name and email, we used an extra lookup. So let's say X lookup, the value that we're looking at. The column that we're looking at, the info in, the column that we want to return information in. And then if it's not found, we're gonna say not. We make this gray since it is a formula and we want the user to know that it auto populates, will take this formula and just repeat it for contact e-mail over here. We'll update contact name to the return array, which is our contact email. And now we can select our different customers and have this information auto populate. And if I come over here and create our email, we can see that our automated e-mail is going to Connie. While we're here, why don't we touch up a couple of small little things. I'm gonna come over here and fix up these buttons a little bit. I can go to Shape Format. And since I highlighted all these buttons while holding control, just a little trick over here, we have these lines. You have this aligned function where we can align middle. So they're all lined and then distribute horizontally, which is going to equally space out these buttons. Okay, so that's it for this video. We'll keep going in the next one. 73. 3.7 Quote Tool - Check Attachment Exists: Well, we are creating our email function here, where we click Create email and automatically pop up this outlook e-mail. An issue that I realized we need to address here really quick, is that if we go to quote number six and click Create e-mail, then we get this error that says path does not exist. And that's because we did not generate a quote for Quote number six yet. So they're either is now folder or of course is now Excel file or a mix of both usually. So if we come over to our folder here, quote files, and we see we don't have a folder for quote six. When it's going to look for the path that we're going to attach the Excel file. It can't find it, and that's the error that we're running into here. This is simple fix. We're going to use what we've used in the previous video, which is just error catch at the beginning of our subroutine and throw an error if the file isn't found where it expects to find the attachment. So this is a really common theme, which is at the beginning of subroutines is where you want to catch all the issues and notify the user if something's missing and the process isn't going to complete successfully. So as usual, it will come up to the top of our subroutine and will start to type in some code to detect errors and let the user know if it happens and stop the process. In order to do that, we actually need the attachment path. So I'm going to backup here and actually come down here to check the attachment path after we've come up with it. You may remember the code here is if then DIR, which is going to check whether a file or folder exists. In this case, we are looking for a file that's going to be the attachment. So we're gonna say attachment path. And before I believe we used VB directory because we're checking whether the folder exists. Now instead, since what's a file? We're just going to say VB normal, which is what we use for a standard file. And then if it's blank, parentheses here, then that means attachment file does not exist. So now we'll throw a message saying file is not found the following a path. We'll say VB line feed. And then we'll display the path of the user just so they can investigate that they wanted to. So anytime I'm doing something with paths, I lead to display the path to the user and the message. So that way they can navigate to that specific folder and confirm for themselves what the problem is. And then just like before, I accidentally hit Enter there, so I'll hit Undo and it comes back attachment path space. So the problem is I'm in break mode, so that's why this keeps popping up. So I'm going to hit stop. You go to our next line here with that underscore and we'll say have another BB line feed and another leaf vb line feed will say process. Then to make sure we actually stop the process and don't continue with generating our e-mail. We're going to hit end here. And one thing I wanna do is this set Outlook message to being a new message. Because we do our validation over here. I don't want to create our Outlook message even if it's hanging in the background because as we saw before, it doesn't actually pop up until we run this display line of code here. I don't want to create a message if we're going to run into this issue and stop everything abruptly. So instead, I'm going to take this line and move it down here. So we're basically going to say validation. If I was going to be really explicit, I'll actually say data up here. We have our validation here. And then create e-mail is down here. So we broke it into these different sections here. So if we have a validation error, we're not going to have started our process at all and end up with possibly some processes or an Outlook message that's hanging in the background. Let's try this out. I'll hit Create email. You see the quote file is not found at the following path. Process will be stopped. Now, if we create the quote, Let's see, we have an issue here. It says I is not defined. And honestly, I noticed this way back when we record this video. So that was a few videos ago where I noticed that even though we have Option Explicit here, it didn't make us declare i. So that was a weird scenario that I just kinda put off. But the problem here is we did not declare the variable I. So we're going to call that a long, which I think should handle that problem. I'm in break mode, I believe. So. I hit stop here. It create quote. And we're doing the same thing here where it's catching an error. So at least we're not hitting VBA errors. The user, in this case, we know what's going on, but if it was another user who wasn't familiar with the code, they're getting good arrows here that's telling them what's going wrong and stopping the process. So it's telling us that there's no subfolder for quote six. Cyclic create Open Folder. Now we've actually created the folder for quotes six. I hit Create email. We still have this problem where the output doesn't exist. So now we need to create the quote, which is generated here. File has been saved. We click Okay, it saved automatically. Now we finally click Create email for quote six, and we have everything ready. So the email successfully auto-generated. 74. 3.8 Quote Tool - Add Total Price: One little thing I wanted to add with this video, which hopefully should be pretty quick, is that I forgot that I wanted to add our total price. So we have our extended price for each of our lines on the quote. But typically for quote, we are going to want to tell the customer a final price over here, total price. And that is the sum of these lines over here. So we're just going to use an Excel formula. Again, make this gray. And now what we need to do is add this onto a quote template. So if I come over here, we'll change this to coat number seven. I can't create the quote because I don't have a folder yet. So let's create our folder with our nice button that automates that process. Then we click Create quote, and we generate our file. And it actually closed with our automation here. So we'll open up the template and see that we don't have our final price anywhere. Let's go ahead and add that. I think we need to set this up in a template. So in our spreadsheet over here, I put final price at the top, just so it's easily visible. But typically for an output, I think a more typical place to put the total price be here at the bottom of the table. So this is our quote seven output. This isn't the actual template that we used from previous videos to start to quote. So this is an active what we're gonna do, but I just want to draft up how this might look. So basically, we want this to say 310 over here. When it's done generating. And we'll do some little things like you're probably noticing that this is not in the format over here. So we can fix that. Now that I'm realizing it, we can do the same thing over here. We want our quotes to look something like this, just to clean it up a little bit more and add this important piece of information here. Let's close this. What we really want to be working with is our quote template. So this is what we start with when we generate a quote. So let's take a look at this here. The first problem we had here is that we're maybe not the first problem, but the easiest problem to solve is that we hadn't numbers here. And we're gonna put this in accounting format. And now if I go over here and I accidentally added a row, if I come over here and I delete our rows, and then I type in here and add a new one. You see that are named table here actually retains our formatting these cells even when the table's cleared out, when we start adding rows back in, it retains the formatting notation that we have. So all we have to do is make this the accounting format. And it's going to stay there when we populate it. And in fact, I'm going to right-click and make sure we delete our rows. And then try this again. Let's see, I'll save this template and we'll try to scan. And we actually are hitting an error here. You can see that the file actually did save correctly. And we have our formatting that we want here. I'm going to close this. We still have this problem that we hit this error over here. In another video, maybe I'll show the details of that. But what I think is actually happening because it correctly prompted me to ask if I wanted to save over the file and I hit Yes, and everything looked like it worked correctly. What I think happened is this is erroring out because I'm just storing all my files on my OneDrive, which is a Cloud Sync folder. That's a whole other topic. But we're creating some problems with our OneDrive clouds sinking of files, making the system think that there's kind of file management conflicts going on. Anyways, we'll continue what we originally wanted to do, which is continue working on our template. We have our total price. Now, what I wanna do is come down here. When I say total price. We'll worry about the formatting too much here. We'll create a name for this range so we can place the information there. Let's make sure that it is this accounting formatting type. Clear that out. And then the interesting part here, I believe, is because we're working with our name table here. When we insert rows, the way we wrote this code originally, it's going to add rows this table, but it should know to not overwrite this row over here. Again, this is the continued benefits of using a name table. We aren't actually typing into these cells and overriding this stuff, just like we don't override this note over here. If we had, if we add at ten lines this quote, it's going to know that this range is pushing everything under downwards. And again, just as a stepping stone, Let's actually try this thing out. We're going to make yet a new quote over here. I'll keep making new ones. And then we also won't run into that kind of OneDrive file error message that was popping up. And we can just avoid that, will create a new quote here for quote. And you can see that popped up and even from our screen over here. We can open it up so it stays on the screen. It pushed the final price down. While we're working on this, Let's go to our code over here for creating the quote. And we can even comment out this line that is closing out the quote file. Because we're gonna be working on this. We can just manually close it out when we want to and when we released this for a user to potentially use, you can make these automation features, but you can add these little quality of life features that saves them a click. But for us we want to see as much as we can so we won't close that file since we're working with a template. Now what we need to do is actually come back to this formula that we had up. And we want to make sure when we're generating the quote that we're bringing in the total price. So over here, we should have some information of where we're bringing in our information from our source file over to our destination file. So here we can add total price as a double. In fact, again, we'll do it as a string so we don't have to worry about types is just a visual output. So I think this will work. It will change it if we need to. Take total price equals this work. Got sheets that may range and total price. And so this is getting the information from this cell right over here. One thing to just touch up since we're here, is we have this written three times as we've gone over in our other lesson, that we can use a width statement over here. We don't need this period here. We'll end with statement. And then to make sure we have our formatting readable. And I clear this out, and this is the same thing. We don't have to type this information over and over. I know it was actually more work in this case to fix it because we didn't do it at first. But this just makes everything a lot cleaner. Well, we don't have duplicate information. We can even do the same thing over here. So I'll cut this, say with that, replaces this information with indent out. And that's cleaned up a bit. We don't have to do it absolutely everywhere, but I just want to get used to that habit of doing that when it makes sense for us to. So here we're taking our information and we add a total price right here. We want to add that now to our output. We wanted to range, we named the same thing, coal price here, value equals. Now, let's go back to our co-creator. We can make yet another quote here. We'll create our folder. File has been created, or folder has been created. Rather. I create my quote, pops up. Formatting is fixed. We have our total price field, which is now automatically populated. It pushed everything down in the formatting output is just like what we wanted. We close this and you see that worked commenting out the line that would close the file worked and it stayed open this time. And here's our file in our respective folder. 75. 3.9.1 Quote Tool - History Log - Start: Now that we have a nice decent quote generator over here that includes the functions from quickly filling out a quote with some basic inputs. Thrown some butter pecan here, haven't used that yet. We add our item and we can create folders. We can create a quote. This is building up over here. We have our butter become line, and we can even create our email. I want to move this to the next step. So the next big feature that a business that might use a tool like this may want is to go from something that's just generating the quote and the e-mails to send out to actually logging all of this information. So after you send out many quotes, say over the course of a quarter or a year, you have all the info about the quotes that went out so that you can review the information and kind of have more data about your business. And then we can start to get into things like data analytics of figuring out how many quotes went out to which customers. Eventually even your win rate of how often they turn into orders and things like that. So for the next series, we'll move on to building a database that will automatically take this information which we've already filled out and submitting that to a data table that we can keep records of everything. Review later. I'm going to slowly work our way up. So we have a bunch of different options of how we can do this. The first one I'm going to do next is storing this information just in the same Excel sheet. And of course we can then work our way up to different types of databases. But we won't get into that now. We're going to slowly build the robustness of this thing as we go and take the slow steps so that we get all the training involved as we build upon a tool like this and handle more and more complex processes with better and better automation. So to get started, let's make a new tab. So for example, I'm going to just call this quote log. Now we come back here and let's look at the information we want on our quote log. We have things like our quote number or customer or contact. That seems like all important information or total price. So let's kind of plan this table out. So we'll call this, our quote log at the top will have something like our quote number. We'll have our customer name, we'll have our contact name. In fact, for now, I'm not even going to have our contact name. Let's just keep this data as minimal as possible. We can add that later. But as we get into the idea of databases and data structures, we're going to start to see the idea of not repeating data. So if we have coat number one here and we have our customer name as wholesale ink. I think it was if we started to store data like this, we actually have a cross-reference where our ice cream wholesale ink customer only has one contact and that's clay O'Neill. And so as we store this data, we actually don't need to store the contact name necessarily right here. We could if there's a good reason to save that time. But we could always do a lookup of our customer name against this data assuming that it stays stagnant. So we might want to change this later. But for now, this is kind of redundant information because it's always this one-to-one relationship. If we have our customer name, we can always look up our contacts. Our total price here. If we have this information in our total price, we don't need this information because it's just a tool for us to add lines to here. And then you might want to store what lines you have on here. But we don't actually want to make a crazy column like this. You can kind of look at this and try to think through our data structure. And imagine that it's going to be difficult to come up with how we can place all the information about these lines into here, which has a single row of information for a single quote. We have quote too and some more information here. So let's set that aside for now. For a quote, We just need something like this. So I hit Control T. So we can declare this a table. And we have a basic table here. When you get into more common software systems that mid-size the larger businesses use, such as an ERP system, which you might be familiar with that term, which is enterprise resource planning. A common idea here is we have these lines where we need to store this info and we have this header info, what I'm calling the header info, which is that when we have quote ten, we have some stuff that fits on one row of data, just like we created over here. Then we also have this other information that's related to quote number ten, where we need more than one row of information. So for example, over here we have quote one. But then I'll create a new tab over here, and we'll call this lines long quote lines log here for the header. If you say Quote number, and let's say we're on quote one here. In fact, we're looking at corp ten. So why don't I just changed this really quick. So it's the one that we actually have on our Main tab at the moment. So we have quote ten, and then we have this information over here. I'm just going to copy this from an e-mail and I'll paste this over here. You can see we have our line number, item, description, quantity, units, unit, price, standard price. That each of these lines all corresponds to quote number ten. Let me turn this into a table format here we'll do Control T again, set this up like this. And you can see we have two tables in the two tables combined hold the information we want for Quote number ten in this case, where we have one thing where there's only one row of information for the quote number. And we can even put our total price here for reference, so 375. But then we don't want to repeat our lines in here. Then we're kind of mixing and matching our information. You can see the columns won't line up for us to put our lines in a table that's set up like this. But then we have a separate table that has our line level information, which is information that needs multiple rows of data for R1 record, which in this case our record being our quote number of ten. This is a really common data structure you'll see across businesses. And the terminology that I usually see in that I use myself is that this is considered the header level and then this is considered the quote level. And this actually reflects a lot of your quote formats, which I'll open up here. You see our naming is because our header level is up here and then our lines level for quote, often very similar for invoices and purchase orders. That you have. A table at the middle, which is your line information, which can be one line or much more than one line in relation to this record, but your header is just one piece of information in relation to the record. So hopefully that makes sense. Maybe you've had some exposure to this idea already through your business or job, and maybe you haven't, but when you come across it, you'll start to recognize this same setup of header in lines. So we have essentially created two tables here because we want to keep track of our lines. Also, it might be the case that you don't care about your lines and you just want this total of the quote. So that's possible too. But I wanted to address this and we'll set up both of these at the same time because they'll use similar concepts. If we came over here and actually clean this up, just like we did for our quote logs, we do have some redundant information, which is that our description is always the same. If we know our item. This is actually a redundant column which I can delete here, because if we need to know the description of this line, we can always take our item and do a lookup which has a one-to-one relation between your item number and your description. If we come back over to data, actually, we'll see that units is the same. So this is just more redundant information that we don't really need to keep track of frightened now, unless we have a good reason later and we can always add that back in. Now we have our unit price. I'm actually going to leave this. This is more information, not necessarily about automation, but how businesses might run, but I think it's worth getting into anyways, I'm going to leave the unit price, even though using logic we had before, I think we have our unit price right here, which we do. But there's a chance that unit price might change. So a lot of times some of this other stuff is unlikely to change, but your pricing might get updated fairly often. And then we want to be capturing the actual price we quoted at. And then if we go in here and we change from our master table the price of one of these items. We don't want our quote lines, which is more of a historical log to change. We want it to remember the price that it was quoted at. And then we have our extended price over here, which we actually don't need because we can always calculate that with our quantity in unit price. So the important thing here, I think, is that I wanted to cover when it comes to storing data, especially data that could potentially become lots and lots of data. The historical log like this might become hundreds or thousands, or for huge businesses, even millions of rows of information. You can do things like this to keep it more efficient and not store information that you could figure out when you need it. Because otherwise, we would have had for extra rows here that we might not need. And if you ended up with hundreds of thousands of rows of information over time, that's going to be a huge difference in the memory it takes to store this information. We have some borders over here just from my copy and paste. So I'm actually going to highlight this will go to Cell Style, make it normal, which is actually just going to make it match the auto formatting of the table. We can come over here. We'll make unit price in dollars, total price also in dollars per half the formatting. And we've kind of set up these two tabs as our database, that's going to be our history logging are quotes as we send them out. So that's just the framing here of what we're going to use to store our information. In the next videos, we'll get into the actual code that's going to manage this information. 76. 3.9.2 Quote Tool - Log Header Info: Now that we've set up the framing on our Excel sheet of how we are going to store some basic information about the quotes that gets sent out. So we have our header information here, in our lines information here. Let's get started in thinking about the process of how this will functionally work. So let's say we're working with 11. We create a new one here. And I create my folder. This is our workflow here. By the way, eventually we can tie this all together if we wanted to, we won't bother right now, but we could make it. So when you create quote, it will also check if there is no folder, it will create the folder for you. So you even have to click less buttons than the three we need to click here to quickly create a folder and then a quote. We could combine them. We're going to deal with that for now. You then create a quote after you set everything up, we'll just kinda leave things as is for now. Then you hit Create e-mail that will pop up the email. The catch here is that this email doesn't go out until I hit Send. It's actually really easy to make this e-mail automatically send out. But I typically haven't done that because most users aren't comfortable with emails just flying out in their name without them reading it over first. And a lot of times you might want to add more information to it, edit a few little things, or add somebody else that CC. So it's nice to just pop up. And if you'd like everything, you click Send Yourself. Actually really quickly. Just show you if you come over to create email, where we type in display here, we can actually replace that with send in. This command will make the email just go out without popping up and displaying first. So we're not gonna do that. We're going to leave it as display. But the catch here is that we want to log this information into our history after we know that it went out to our customer and we've moved on because we have to click the Send button and outlook for it to go out. We can't detect that the user has clicked the send button in Outlook. So if a person creates the e-mail like this, then realizes they made a typo or something like that or that they don't like the way this is setup. And then they close out the email. They might not be done. And maybe they walk away from their computer for the end of the day and then they come back tomorrow to finish working on this quote 11 here. We're not ready to log this into our history. What we wanna do is logged the finalized quote when we're done. So we don't want to log one. We're not sure is complete. So instead of time does to our create email, we don't know whether the person created an email just to check it out and it's going to change some things. So instead, at least for now, we're just going to make a whole new button. Ce, mark as complete. This button marked as complete is the button that for now a user would just press at the end of their process to say, Hey, I'm completely done here. And that is what's going to move this information from here into our log for our header and our lines. Now we're explaining our workflow and how it'll work. Let's start writing up the code that's gonna do this. Let's create a new module over here for this information, we'll do Insert Module. One thing you might notice here is we actually have these files hanging open in memory right now. Even though over here in Excel, they're not open. That's something we could address in another video. Or maybe I'll put it earlier in our class, but we'll just set that aside for now. That's not important. We're going to create this module over here. And we'll call it database. For now. Maybe we'll rename it, but it's just going to handle database related stuff. So let's set this up as log record history. Now what we can do is look at the information we need. We'll start with our header, which is going to be really easy here because we just have three pieces of information. Using some of the concepts we've already shown, you can probably imagine how we can do this. We just need to grab the information from here and then add a new route to the state of table and put that information into that new row. There's only three pieces of information. So this shouldn't be too bad at all. Even on this tool, what we've covered already, this will be a lot like the Add Item process. So let's go over here. Let's set this up as usual and split up our code in our user interface. And we need boat number, customer name, a string, and total price. As. Again, we'll just make that a string for now because we're not doing any math with it. It's not a big deal that we're using numbers as strings. Now if we were gonna do some math with that number, then we want to be more specific and probably call it a double quote number. And we've done this a bunch of time at this point, is range number. If we want it to be more explicit, we can make sure that we are working in our sheets called name. We use a width statement here. Then if we put the period over here, we'll know that we're explicitly saying we're using the range from our main sheet value. Then we can say that the customer needs. Equals range, that customer name, that value, and our total price equals our range called total, total cost. Now, if I hit F8 and we'll step through this just to make sure I didn't make mistakes. We have 11 customer name and total price. So let's continue building this. I'll put a comment here and say add new route to quote log in popular. So we need to address this table over here as an object. And then we'll add a new row just like we have in the past. And as I'm saying that, I'm realizing that I forgot to give these a name. So let's call this table, table at our log. And while we're at it, let's name our lines table over here. Table. Now that we have a good name for our table here, we'll create an object or list objects, so we'll call it table header as a list object. Set table header equals. Now we're in a different sheet, so we're going to say our sheets. What log? Which is what we named our sheet down here. We'll say list objects. And it was tabled quote at our log as the name of our table. Now we'll prepare our lists row object. So we'll declare it up here as a list row. And then we'll set this list object as a new row that we create a table header as our list object, that list grows. So creating a new row here and then declaring it as r l row variable while we do it. And now that we have our row variable, I'm gonna do it this way before I fix it, which we've done before also in say, on that row, the first element is our boat number 23. So our second element, and then our third element over here, is going to respectively be our customer name and our total price. So we're going to have our new row and then 123. And that was just as a demonstration. If you've watched the other videos, you'll know that I don't want to do this. I actually want to say table header, that list, column, Quote number, that index. Use this notation over here. That's using our column name. Instead of hard-coding the column number over here that way. But my accidentally deleted this, so I'll do a Control Z. In that way. If we move our columns around or add new columns, then we won't have to change our numbers here. And over here, we have our total price. So let's try this out. We'll put a message box at the end here and say header info added exclamation point. Now let's tie our button to our new macro over here, which is log record to history. We'll click this. We have some error here. Let's take a look at that and has a problem with this line. And right away I'm noticing that I forgot the S over here on list objects. So this needs to be plural because there's a bump. There could potentially be multiple list objects. And then we're telling it which one we want, which is here. I'll hit Play to continue header info added to log. In. Here we have our new information added to this table. Just to make things look a little cleaner, I'll remove the grid lines since we already have this table over here. Now we can try it again. And what we're gonna notice I think, is that we'll deal with this later, but we probably don't want the person to be able to do this and add the record more than once and then have kind of duplicate information. So we'll probably add some sort of error catching in some way to handle that later. So I'll break up the video here, and in the next one, we'll move on to adding our line items to our history log for lines. 77. 3.9.3 Quote Tool - Log Lines Info: Now that we have our function that can log the header information for the quote over here to our header table, despite letting us add duplicate records here. Let's do our lines next. We'll do this in same formula because of course we don't have two buttons here that's going to say log your lines and then log your headers. This is all going to happen at once. So we'll keep building this over here. And new row to add or log, just to clarify. And then we'll break up our code a little bit. We'll say add rows to vote Wien's law and populate. That's what we're going to have over here in order to set that up, just like we have a object for our header table over here. Now we're going to need to do same thing for our lines table. And so we're talking about this table over here. So we'll say cable lines as list object. We already have L row. I'm kinda looking up here as I'm typing. So we can reuse that will set enable lines as where actually equals, equals sheets. Well, Wien's law, I believe that's what we call this worksheet, which it is that list objects back table, lines blog, I believe was the name of our table. Now to add our information here, that stuff, let me make this bigger here comes from this table over here. So in order to transfer the information, let's create an object for this table so that we can loop through every row in here. This is a lot like when we were creating our Excel output template. We're going to loop through all this row. We're going to loop through all these rows and then move that information over here. It's a little bit less information in this case because we narrowed down the columns that we want to keep track of. That just five here, really for, because this one's a really easy one. Let's come back over here. We need to set up our source table. So what we call it table source lines as this object also, we can set that as a source lines equals sheets. And that's our main tab. And it's in our list objects, table lines. We can come over here and double-check that we have Table lines every year. And of course it would throw an error if I made a typo or wrote the wrong name there. Now that we have this, we are going to loop through all the rows in our source information right here. So for I equals 12 tables Source Lines that this rose that count. We're going to loop through with I as our index for each row here. Now, just like we did for our quote output file, Let's set our L rho equals. And then from our source stable or source lines that Miss Rose. And this is going to loop through each row and then set our L rho object as this information over here. We need to declare our variable since we're using it as a long. Then just to separate our rows, we're going to come in here and we're going to add a new row here for every row over here. So instead of just reusing the same list object or L rho, and that may be getting confusing. Let's say new l rho as another literal object. So now we can say set new l rho equals table lines. And you know what? Just to make things a little more clear, I'll change the name of this to destination lines. So table destination lines, that list of rows that we have our source over here. This is our destination. So we're going to set our new row in our destination as we create a new row there. So in this case we're going to loop through six, actually five rows here. So we're going to run this loop five times. Each time we're gonna get info from our source and create a new row over here. We're going to split this up where in this section we need to store our information. So let's say dimension, line number as string, Item number as string. Let's remember what columns we had over here because it wasn't all of them. So we have lines, item, quantity in unit price and unit price. And let's get this information from over here. I'm gonna do the same way that I did before, which is start off with just reading our indexes before we update to use our column names. So we can say line number equals our source row range, one, in this case that value. And then our item number equals L rho range to that value. Our quantity actually skips one because we're skipping over description, which is three. And we're going to column four. And unit price, which I believe is also going to skip over our units. So skipping over five and going to range six, that value, and then typing that just for clarity at first, we can actually come up here and use the same concept. We're going to say Table source lines. So the table that we're looking at and say our list columns, we'll type in our name, which in this case I think is line number. Index is going to replace the one in this case. So line number. And then I can copy this. Let me just put this information in here for now. And then the second line is item. Next one is quantity. As I'm copying these headers over here. And then our last one is then now that all this information is stored into these variables. We're going to throw this back into our new row. Since this notation is kinda long, I'm just going to copy it. So we're not talking about our L route. We're now talking about our new l rho that we pushed into this table over here. Our range isn't from our source lines. Visit information. This is the mistake we made. These I made in a few videos ago where I forgot to make this change of our table reference. Line number is still the same thing for our column name and we can change that if it was different. And now we are not getting information from here, but instead we're going to set that information with the line number. One thing I'm forgetting is information that we're not moving from the table is our first column here, Quote number. So we're going to take this coat number column. We're going to set that as our quote number, which we already used once for header information. So that variable was already prepared for us to use. Now we can take this and we need to go from line number two, item than quantity, then unit price. So now I have to update these here for item, quantity and price. And then we'll update our variables were used, were using over here, which was item number, quantity, and price. Which is just mirroring the variables we prepared up here from our source. And that's going to run through the loop for each row creating all these new rows over here. So if we're lucky, let's see if this works. We'll come over here. We'll say mark as complete, you have a subscript out of range. And it has a problem with line number. Over here. We have our destination, our list columns, line number. This says Lines number plural. I believe it should be singular to match over here. And to make more sense really. So we have this half broken code. We're actually still in the middle of it, so I'll hit Run and we can continue on our way. And here is our five rows from the front page moved over to our lines log. And then we have yet another duplicate over here. Let's go ahead and delete these rows for Quote number 11. And we'll change our message boxes, say quote info added to history lock. So now let's try again. Mark as complete quote info added the history log, and we come over and we see our header information is added here. And also our five lines of line information, or add it over here. 78. 3.A.1 Automate Get Data From Many Files Intro: In the last video, we finished adding a function that logs information about each quote into a data table as we complete each quote. So when we click the Mark Complete Button, we move the lines data, for example, and the header data on another tab into here. So we sent ten and as we've marked a complete, we move all the lines into this table. And then 11. And then when we do 121314, we're going to create this giant database of all the information in this table, keeping track of the history of quotes that went out in which lines are on there. This sets us up for a bit of a tangent here. This sets us up for a bit of a tangent. But it also gives a chance for me to show you something that's really common need in all sorts of different scenarios. And we're going to run into it right here. Which is that because we added this function with quote ten, we have a bunch of quotes that we sent out earlier and just these demos of one through nine that is not in this data table. And so what we really wanna do is get all this history all the way back to the beginning from our first quote. We wanna do something like coming to quote one, which actually doesn't have a file in it. We probably just made the Excel files and output. You go into quote to open it up and you want to do something like grab this information. I'm just gonna put it down here for now, place it like this. And then we're going to need to come back here. Go to quote three, open this file, grab this information, and you can see it will basically have to keep doing this. So this was quote to an N3. And then we're going to do four all the way up to nine for us to fill in our history of these quotes that were before we added this feature. And that's a way to catch up our database. So we don't have this gap where we don't have our earlier quotes. And I could continue this process because we only have nine so far. But this gives us a great chance to show you how to automate something like this, because in a lot of cases we won't have nine. We'd add a function like this, and we'll realize we need data from all the quote history, which could be hundreds or thousands of different quotes. And there's no way that you want to open up every file the way I just showed you for these 2.5 to do all that cut and pasting of the data into our database. So this gives us a chance to go through this process. But you might also use this process in a ton of other ways where basically you need to open many, many different Excel files to fetch data, in some cases hundreds or thousands, and put it all into one place. And we want to automate that process. 79. 3.A.2 Loop through List of IDs: All right. Starting off to create a tool, I'm going to separate out this tool that we're going to create for this process of opening all these Excel files and pulling the data out of them. So I'm just going to do it right in our creator right here. I could start a new Excel file, but there's not really a need to do that. We'll create a new tab, and I'll just call it tools just so we can add miscellaneous functions. It's not officially part of our quote creator that we've been working on in the previous lessons, but it is a standalone feature that you could use. And so, for example, it might have some button that says something like get data. And what we want to do in our specific case is we have these folders over here and we want to get the lines data from, quote, one through nine because we only have the data for ten and 11 and going forward. And again, it's only nine right now, but it could be hundreds in another scenario, which is why we want to make sure we know how to automate something like this. So let's start by making a list of quotes. So which ones that we want to open? We don't need ten and 11. So let's go with our folder names right now. We need quote one. We'll keep with this notation over here. And we need up to nine. Right now, we're going to do it this way. And you see, it's this easy to do. Nine And if we had a lot more, you could drag this list down, especially since they're sequentially named like this. There is another method that maybe we'll get into in a future lesson, which is how to loop through a bunch of files and folders if there's not a consistent name and there's just thousands of files in a folder, how to loop through every single file or folder in a specific sub folder without having to know the names. So that's another option you have, but we won't get into that right now. Now that we have our list of quotes, what you're going to imagine we're going to do is loop through this. So let's start a macro over here. I'm going to come over here, over in our co-creator. Let's just keep both of these open as usual. Over here, I'm going to create a new module. We'll call this tools just to match our tap name over here. We can call it sub. Get this three lines. So what we need to do is go through each of these and we're going to need to go into each sub folder. So we're going to need to know the path of each Excel file over here. In fact, just to keep this simple, let's forget quote one, just to keep it simpler. So I'm going to right click and delete this because there's no Excel file in there. Let's just do two through nine and keep things as simple as possible to start at least. So we know our Excel file is in this path over here. So here's the folder that the Excel files in. If I right click over here, I actually can do this copy as path in for example, is going to make a comment right here. This is an example full path of that Excel file and we know the thing that changes is this string. So we have a folder that changes and our file name that changes between quotes and it's just going to go two, three, four or five, six and so forth. So let's keep this in mind over here. I'm going to move this over and let's start to write something. We know that we're going to need a loop to go through each one of these. So in this case, we're going to have to run it nine times. One, two, three, four, five. So as we've done before, we can make this a table of table four, quote numbers. Let's just say let's create our table both numbers as this object. We're going to set this table list object our object variables here as sheets tools that list object as plural, it will pull number, right? So now we just have this really basic thing and sometimes I like to just break here and stop and run even the very small snippets of code that I've written so I can make sure it works. And so now we have acknowledgment of this table here. We've created this list object that is this table here, and then we can create a list row object. So we've done this in our past lessons as list row and we're going to loop through each one of these so we can say something like for each list, throw in table number, numbers, stock list, rows, row, and then if I say all row, that range, that's select for example, let's see, I can delete this and if we stop over here and then I hit run and we had eight, you see we're selecting each row as we come down here. So we already have a loop that's coming through here now. Now we have this loop that's going to execute one loop for every row in here and we're going to construct a path we need to open the Excel file, because what we want to do is take this path and open an Excel file. Right? We can even do it outside of the loop at first just to show you. So I'm going to say dim file path, a string set of file path equals let's do this exact file up here. I accidentally click the help button. I think I'll click okay. I accidentally pressed f one is what happened, which sends me to help page on the browser. So here is our file path for the quote two Excel file and we're going to do something like dim workbook as a workbook because this is an Excel file. We can use this workbook object and we can say, Set the workbook equals workbook, start open and file path. So this is going to open the Excel workbook by the file path, which in this case is going to be for quote two to access it f eight and see if this works. So you see to get the data, we need to open the file. So here we open the file and then I closed it over here. We can actually take this. We're going to open the file path, but then we need to construct our file path here. So if I take this cut that actually and place it in here so you can see here we don't need this anymore, but we're going to loop through each row and it's our L route here. But what we need as we loop through each row is instead of saying, quote, to. In these two locations. We need it to be the value of the cells. So it goes from 2 to 3 to 4 to 5 and so forth. So now we can add a variable that's going to be what changes. So I'm going to say, quote, number as string. And for example, if we said quote number, which is hard to add something here for now, we're going to say quote, one, two, three, four, five. And I think it's a six digit quote number. Now, I can use this variable so I can replace this quote number two here. And we're going to combine this string together and then same thing over here. Instead of this, we are going to combine the string together here. Now, if we say debug print file path. So we're just going to check the file path before we open it. I'll hit play. So we have some sort of issue here and safety bug. I should have deleted this because I moved it down and there's no file path right here since I moved the file path declaration down here. So now file path is blank and is trying to open a workbook blank. Now we're hopping down ahead f eight and you see as we hit file path, we have the exact same thing. This is our file path for quote two, but it is using a variable now instead. So if i change the three, I quote number over here now quote number is three and then this file path is constructed using this variable. And now when I hit the print again, let me clear this actually, I'll move this back up and show debug print. And you see the file path is four quotes, three now. So you're starting to see how we can construct this and change this with every loop. So what we really want this to be over here isn't a hardcoded number, but we want it to be our row, which is what's cycled through each loop, iteration, our range. And since there's only one column, we're just going to type one here. So that is saying the first column of this row and there's only one column. So it's nice and easy and it's the value of that. So now I'm going to stop. I'll hit play again and we'll just jump down to this loop so we can step through it. You'll see a quote number. We are going to be on the first row here, even though it doesn't select it. That's because the macro here, the Vico doesn't bother to select the cell. It can work with it without selecting the cell. It's going to say, quote, number two over here, it constructs a file path. In fact, I'm going to comment out opening this workbook for now. Now, you see on the next loop, quote three on the next loop, it's quote four and so forth. And I commented out opening the workbook, but now that I'm going to turn it back on, it's going to do quote two and then open the workbook and then three, open the workbook again. And so this is going to cycle through all of these rows. And each time it's going to run this line of code which takes the constructed path and opens the workbook. So let's go ahead and try that out. We'll get crazy and even take off this break and just hit play and go for it. There's one. And you see all these workbooks are opening and now we have a bunch of workbooks that are open from quote to looks like it's out of order. Quote two, three, four or five all the way through in nine. And this is how we are going to use this loop and cycle through all of these workbooks and see how quick it was to open up nine workbooks. This is where the automation could really start to take place. And if you have hundreds of files or even thousands, although with thousands, you might want to walk away from your computer and get a cup of coffee or something like that. It will take at least a few minutes or longer, depending on how many files you have. But we're creating a loop that is going to open all of these files. So this is a good stopping point in in the next lesson, we'll move forward with what we can do as we open all these files and have this automation process where we only need to write the code inside this loop, and then this loop is going to cycle that code through. However long this list is, in our case, are equal numbers here. 80. 3.A.3 Loop Open Files and Get Data: Now that in the last video, we created this loop where we're going to cycle through all these quote numbers and open each Excel file. We don't want to get left with all these Excel files open that I've already manually closed, but we don't want to have to deal with manually closing done. So now as we open the workbook, we can close the workbook after we're done with it. And since we have this workbook object WB, I can just say WB DOC flows and that will close the work. And then of course we don't want to just open and close it. We just haven't gotten to the real code here, which is get information and place it into a. So this is just a comment right here, but we're basically going to put code here that does, which is get the information out of each file. And then when we're done with getting the info out of the file, we'll close the file before we get to that, you can just see how this works. That this is going to open the workbooks and enclose it right away. Cycle through this list of eight workbooks over here. So let's hit Play. You can see it opens, closes over and over again. And we just don't have any code to do something while it's open. And that's what we're going to write next. And now we don't have all these Excel files hanging open anymore. Let's start with quote to open it up here. And let's open both of these up here. And we want to pull information from our quote lines log. So what we want to do is get our history of quote two through nine. We want to get this data that we got from Canada 11 and all the quotes going forward. But we're going to populate our history. And we only want these columns for this data table because that's all we needed. It looks like we have more columns in our actual quotes, but we have decided in those previous videos, we don't need all that data. We need these five over here. So what I'm gonna do is copy this. I'm going to paste this over here. Let's turn this into an actual table. So I'm going to highlight this and even one blank row and hit Control T to format it as a table will say my table has headers because it's just convenient to keep working with this as a list object. I'm going to say table and make this a name table called table. Hold lines theta, right? So these aren't great names. I'm just coming up with something. Again, this is just a single use case for us the whole history. And so this isn't the kind of thing that people are gonna be interacting with every day. I have the table pulled lines data here. And that's where we're basically going to take all of this. And we're in this case for quote two, we're going to write to looks like we have four lines here and lines items. We're basically going to do this, but inside our loop so that it'll automatically cycle through each file and do all eight of them automatically. I'm going to clear these rows because we don't actually want them over here. We're gonna do this automatically, but I was just doing it as a demo of how to do it manually. And we need to pull this information. So what I think we're going to do, the easiest way to do it, since we have our name tables, is to cycle through each row in here. And as I go through each row in this Excel file, I'm going to add a new row over here, move this data into it, and then go down to my second row and then add a second row. So we're going to do it row by row is looking at this file and moving each row over from right to left. There's other ways to do this, especially if you don't have name tables, the way that we're using named tables here. So a lot of times the data might not have these named tables and using list objects. So maybe we'll come back to that at the end of this lesson. But the way I set this up using named tables and list objects is going to make it a lot easier for us. And that's the way we're gonna do it here, because it's the most straightforward using what we've already set up. Now let's go back to our VBA code over here. And this is where we want to have our CO2 move that data. So what we have over here is a table over here on the right, and we want to get this data and move it over here to the file on the left. So they get that data. Let's look at the data we need to move for each row. And let's just create some place with variables, like we've done in the past. You don't always need these, but it makes it more clear, especially since we're learning here. So you can say our quote number, which we already have. While we say Quote number, only, because this actually shouldn't say our full quote number is just going to say 2345 because that's our notation over here. So we actually need to take the number off of here. So figure that out. And we'll call that a lot because it's gonna be an actual number and not have the word quote or any of the string characters in there, then we're going to need a line number. We can go ahead and call that as a string item as String. Want to yesterday. So just like we did in the past lessons, you could turn these into doubles or more specific variable types. But for our case, I think it's easy enough to make him a string for now until we find a good reason to not. And that just makes it nice and simple. So now that we have our Excel file open over here on the other side, we need to loop through this table. And so the easiest way to loop through this table is to create a list object, object variable over here and our VBA code to be associated with this table over here. That way we can loop over the rows. Let's make another table. Let's call it table. I'm going to call it source because this is the source of our information over here. So that's the list object. We need it to be this table in here. So it needs to be the table that's inside of our open Excel file. We can declare it up here because we don't even have an opened Excel file yet. At least not an open source excel file, which is where we're getting our data from. We open that source file down here with our workbook object. So if we want to get this table over here, we need this workbook which we opened down here. And the name of our table is table lines. So if you say source equals workbook, which means specifically this right excel file that we opened to say this sheets quote over here. So we can say sheets quote by name because they're all going to have the same tag. You could also say sheets, one without the quotation marks, and that means the first sheet of the Excel file. Either of those would work. In this case, you'd have to adapt it to your situation. And then now we have a bunch of list objects again, which is our name table, which is Table lines. And that comes from this name table over here for our lines. Now that we have our table, we want to loop through these. Also. We move through these rows. We need to say for each row in tables source that list. So this is going to loop through each row of our source table over here. But one thing we have a problem with is L rho is already used in this loop. So we use L rho to loop through each row in here. And then while we're doing that, we need to remember another row object and we can't use the same row twice. So why don't we add another variable yet again, we'll call it L row. Source has a here because we're already using the L rho object here. We will say for each o real source, we're going to call this each row of our source table. We'll move this back over here. It'll split it up like this. Now what we need is our line number equals and I'm just couple of blanks here for now. We need an item equals quantity equals the unit price. And we need to extract this from each row of information in this table over here. So our line number is going to be our L rho, and specifically our source because that's the looping through this table over here. Not to be confused with our other Elvira that we use for our quote numbers, that range, and then our line number is one. And I'm going to do this in the lazy way actually, in the past lessons, you'll see every time I do this, I come back and add our code in here to figure out the column indexed by the column name. So we want to figure out item, but instead I'm just saying column two. And our quantity is column four in this case, since this isn't the type of thing that will be used all the time. I'm just going to be lazy and leave these numbers here. You see in the past videos how we can change this so that it goes by column name instead of numbers, which would be more consistent if you added and move columns around. But we're just going to be lazy and make this column for column five over here. Actually, we want come on like this. And then now that I have this row of information, basically I have this row. I need to move it back over to this file over here. So now we need to get our table over here so we can add a row to it. And we don't have a list object for this either. Let's come back up here. Let's make a table destination because you have your source where the data's coming from, and then your destination where the data's going to say that they list out. But also it needs to be outside the loop because this is going to loop through every Excel file. We can even say that Excel file over here and then this other loop or something else. This is for each row of lines data in Excel file. And so there's only one destination table. So we don't need to declare it over and over again in these loops. We just need to do at once, which is why I'm all the way up here in our, outside of our loops. And then we're going to have the same problem where we want a specific list route if we can help it. So let's make a l row just for this table, because we keep working with these rows. We essentially have three tables we're working with now, each with rows. So we're going to call it L route destination to this row. This is just an object variable we're going to use to manage the rows in this table underscore destination. Now let's set this table equals sheets, tools, list objects, and whatever we call this name table over here. I'll even come over here and I'll just copy and pasted table pulled lines theta. So now we have this table object, table destination, which stands for this one over here. We've gotten our information from our source. Table are green table over on the right, one relevant fell. Now we're ready to add it to our destination. So we can say set L rho, destination equals and then table destination not list rows, dot add. So basically we're going to add a new row to this table over here. And then we're going to call that new row that just got added. L wrote destination. Now we can say L rho destination, that range, column one equals something. We'll just leave that as a placeholder. We have five columns, 1234512345. So 23, 45, and our line number goes in our second column. Item goes in our third quantity and fourth unit price in fifth. And then we haven't figured out our quote number yet actually. So we'll come back to that. So now we're going to loop through each row of our source, and then we're going to create a new row over here on the left and our destination, and then move the data into the new row. And then we'll just keep doing that process until we run out of rows over here on this table. Sorry, we got, we're going back-and-forth here. And then when we're done looping through each row, then we close our workbook, and then we do it all again. Let's see if I can make this smaller and maybe we can see more than one file pop up at once. And let's go ahead and try to run this thing. And let's see how it works. In fact, I'll hit F8 so we can continue all this up. It gave me an error. That is because I say next L rho here, but our loop is using L row source. So we actually have to say next L row source over here. I'm going to close this file. So we're starting from the beginning. And now I'll hit F8. And let's see if we got things right. I'm not usually this lucky to not have made us small error or at least the typo somewhere. Well, let's see how it goes. And when we got here, this is a quirk of VBA as you step through code, sometimes when you work through a loop, you hit a line of code. I think it might be this one where you open the workbook where it stopped stepping through the lines one-by-one with F8, it hits a line of code and some lines of code would just get everything moving again and running all the way through without pausing line-by-line. And so that's what just happened here. Somewhat unexpectedly, you actually see all of this data pulled in. This data, it looks crazy because it pulled the formatting from the header because there was no data in here. So if I just come over here and highlight all this data and do cells normal, It's going to use the default formatting of the table again before it was inheriting the formatting from the row above, which was the header. And we actually have all this data, and I don't actually know if it is correct, but it looks all right. It's got all this data. I don't know if this is actually from all nine quotes or not. But I'm going to use this as a stopping point. And for our next lesson, we'll dive into polishing this whole thing up and we need to clean our quote numbers from here into just the number value so that we can populate this quote number. And then we can double-check whether or not this data's correct and see which lines correspond to which quote. Once we get this column populated. 81. 3.A.4 Convert Tag Format and Test: So leaving off where we were in our last video, we had done our first test run of our function over here. And it pulled all this data, but we don't have a quote numbers, so we don't have a way to know whether or not we got all the data from these eight files correctly or not. We need to take our quote number, which we're getting from here and parse out just the number itself because that's how we want our data to come through on this row. The match how we had our data table over here for our history. Let's do that. I had already set up this variable quote number only to be our quote number with just the value of the number instead of this full name, the word quote in it. So let's go ahead and set this up. We're going to have to do it in our loop because we are going to be looping through each row here. So here's where we have our quote number with the word quote minute. One thing I can do is say Quote number only. This is a long So it is just the number. Let's actually change that. Let's change that to a string. There's a few ways we can do this, but I'm gonna do this so that we can see all the steps. And since it's a string, we're going to manipulate our quote number here, the one over here, and slowly through a couple of steps, reduce it down to just the number. And since it's a string, we'll be able to do that and not get all these errors about it not being a number. So by doing that, we can take our quote number here and we can do a BBA. Replace. The Replace function, takes this string, we're going to replace the word quote, and we're going to replace that with nothing. So what this does is basically takes a string like this, I'll show it up here. It's going to look for anywhere. We have the word quote and it's going to replace that with something. But in this case, since we have an empty quotation mark in here, then it's going to replace it with nothing. So down here, we're going to end up with just the number string on the right side. And it's going to have all the leading zeros. So let's try this out. I'm going to hit F5 to run. We jumped down here already. I hit F8. And if I hover over here, you can see it's stripped away the word quote and we're left with number only it has all its leading zeros. So it's not exactly what we want yet. But now we're just going to use the same exact string over here. And I'm going to take what it is currently, which is the number two with all these leading zeros. See if I can make it show up. I can make it show right now. It's not hovering because of some situation here. But basically I'm going to take itself which has the leading zeros, and I'm going to convert it to a long. So you can see this expression over here actually, where if I type C LNG, C is four convert, I think maybe it doesn't stand for convert, but it is a common notation in VBA. And it's going to convert whatever's in the parentheses to a long. This is going to take it zeros and convert it to the actual number. So if I come over here, I run this again. You see this is the two with the leading zeros. But once I do this, it's only the two itself because it converted to a number which removes all the zeros. There's a common convergent thing. If you convert something to a string, it's CFTR for C string or C I and T for C integer. Or see EBL four convert to double. So this notation, it's common for variable type conversions. Now we have the number only when we're down here for each row. This is where we're looping through each row of information as it gets added. But we don't have to change the quote number because when we're unquote to all of these lines are going to be two. It's going to say two to 22 here. You see this is from quote three probably because our line numbers start all over again over here where we left it blank. We can say number only. And that's going to find the quote number that we are getting from up here. So let's stop this. Let's turn this off. And then I'm going to delete all these lines because balance from our first test. So let's run this again and see how it goes. It opens to quote, to quote three. You see there's kind of patches over here on the left. That's because it's running so fast that the screen isn't updating quick enough. So you see it all magically shows up at the end. That's just the screen catching up with how fast everything is running in the background. You see two here, three here, a lot of this stuff the same because if you play back those videos, I was leaving the same information in there. So let's test this out to see if a poll to write data, we had a quote form. Let's check quote two over here. And our lines over here are the nella vanilla spoon, 51015105101500 pieces. We have our unit price of 1010101. And you see that works. And then let's just pull a random one to see, let's check quote eight. So we're not going to check off these and record that video. But if we check another random one in the middle, then that'll be a good tale here. A lot of times what I'll do when I have a lot of data to check if we're pulling hundreds of files, for example, we're not going to double-check them all that loses the entire point. But I'll do something like check the first one, the last file, and then any random file in the middle. And that's a good way to check with three data points to make sure that things were working at the beginning, middle, and end. Now we're unquote eight. So we're taking this information over here. And we have spoon and strawberry has 34. We got spoon and strawberry here, 5101055 gallons, ten gallons, 100 pieces and five. So we feel pretty good that we got the right information here and here we have successfully pulled our history from our past files automatically. And now if we want to do something like actually I'll come back here that's inserted into our history. I'm going to scroll all the way down here that was using Shift Control and the down arrow to bring me from here all the way down. I can see down here that we have 32 cells here. And what I might actually do is I'm just going to insert a ton of rows in here more than I need. Grab this information here. I'm going to do a Control C copy, control V paste. Here's all my info and then I have these blank lines that I just added a lot more than I needed and delete them. And now I have my history rolled into our full data table. And then since we added this function, as we work on new quotes, say 1213, the information is going to keep adding here. We pulled this information. You can see we actually pulled in our units over here in the quantity which is an inconsistent format. So we can change this. Maybe I'll shoot a lesson on that, but I think that's pretty straightforward. This is just the amount of detail we need to deal with. But the main idea here is that we see how we could automatically write some code that's going to open up many Excel files and pull data to bring it altogether in. This will work for, in our case, eight different files at a click of a button. And it would work for a 100 files in a 1000 files in more. In certain cases, this can save you an enormous amount of time. 82. 3.10.1 Quote Tool Clear Form Button: Now coming back to our main quote form over here, we're going to add a really simple function in this lesson. So this is just a formality to make this more user-friendly. What we're gonna do is create a quick button to clear out all of our fields here, because we made quote 11 and we might want to start a new one. And we could come over here and clear all these fields out manually. But let's just create a button for it to make things easy. So the fields we want to clear out or all of these white fields here that I'm clicking through. And our table, our gray fields here are based on these formulas. And so we don't want to clear out our formulas because our formulas will adjust automatically as we change our selections. So let's start by creating a clear button. We're getting a lot of buttons on here, so I'm just going to put it up here for now. We'll figure out where it goes later. I hit cancel to not assign a macro because we don't have one yet. And we'll call this button clear all. Now I'm going to right-click here and go to our code behind this sheet. And let's create one called clear. Here's a subroutine called Clear all. I'll just go ahead and attach this button to this macro over here. So if we come over here, we can write a message box that says all cleared or something like that. We can have a better message, but we'll deal with that later. And if I click this, it says all cleared, which isn't true because we haven't done anything yet. I'm going to push this stuff down, this message box down. And up here we're gonna put the code to clear all fields in. We'll create our main tab. So this is gonna be pretty straightforward. We're not going to go over many new concepts here. So just to get this function, we want to take our range, which is in our sheet here. We want to say range Quote number, in this case, that value equals blank. So there's a couple of things we can do here. If you look at a range and we get a whole number, for example, I'm not gonna go over all of these, but there's clear. And then there's clear, just the word clear Comments, their contents, clear formats. So all of these do different things. We could try these out or you could try them out and see what they do. But the easiest thing that I usually do is just do a value equals blank. Because if you do something like, for example, just the word clear and we just ran this subroutine over here against the range. It might do something I can't remember off the top my head, but it might clear the borders, for example, and really changed the cell more than we want. What we really want is the desk kind of cleared out over here like this and keep all the formatting the same. In fact, I can even show you, Let's go ahead and test it. Even though I said I didn't want to. Down here, that's around this in our immediates window and we'll type clear and see what happens. So exactly like what I was worried about, we lost our borders now. And that's why I do something like value equals blank instead, it's still remembers that this range is Quote number. So what I need to do is just add our border back, ran clear out our value, and then we need to do it for these other fields right here. I'm just going to copy this and it looks like we have three other fields over here. We can indent this. Over here is customer name. Let me split this up here so we can see both at once customer name, we have our item number, and we have our quantity over here. And each of these is just going to set the value to be blank. Let's go ahead and try this. Click Clear. And you see a clear these out over here. And these are not found because we have our formulas. They're doing lookups based on what we fill in here, which of course is blank. But if I start to fill this out with random information again, then our formula start to work and they pull the data that we designed for earlier in the lessons. And then the last thing we need to do here is clear our table out. One thing I forgot to mention is here I haven't explicitly, haven't explicitly called out our sheets. So I could say sheets main here, that range to specifically let us know that this range is on this main tab here. But we don't have to because I'm putting my code behind this sheet. So it's not in one of the modules down here. Instead it's behind a sheet. And so this thing inherently knows that when I call arrange without telling it which it's in, it knows to check this sheet that the code is behind first. So that's why I'm able to leave out the explicit call and not worried that something's gonna go wrong. Because I know that this thing is going to default to know and good sheet we're talking about when I use this range, a table down here is a list object. So if I come back to Table Design will remember that's called TBL lines. So for example, here I can call out our sheet, will say sheets main, and then we'll say that list objects. You'll remember from our past lessons in its table lines. And from our earlier lessons, you might remember that because we're calling it this way. I'm not getting these auto-fill options, what's called intellisense options, which is telling me what features I have here. I happen to know that this is data body range about the elite. And as I jumped out of a line, you can see it automatically formatted what I've typed here. It may capitalizations and the right spots capitalize the word delete. And that tells me that I type something correct, that when I give it these instructions, it knows what they are. But it didn't give me an autofill option. And that's because of the way that I'm calling us out. I'm not using an object variable. Meanwhile, we can do the same thing. Could clarify this. I can say table launch as a list object, I can say set table line equals. And this is our reference to this table down here. And then now that I have table lines as a list object, as an object variable here. Now, our code's going to know what properties and subroutines we have for this object, for this list object, and then we have Theta body range about delete. And I just knew that because I had memorized it down here. So this code and this code mean the exact same thing, although you might get thrown off when you use this notation, it's not auto-filling or giving autofill suggestions for you. I'll just go ahead and clear this out. Since I already wrote this, this is the more clear notation I think. So we're gonna take our data body range, which is all the content down here, delete it. So let's go ahead and run this. All clear. Now we can come up for our 12th quote, will make some selections here. We'll add the item, but we have subscript out of range for some reason. So let's hit the bug. I must have broken something before. So let's see what this is about. Okay, So this is unrelated to our function that we just created to clear the form. But I see what's going on here. I'm actually going to stop this video and then we'll pick this up as generic troubleshooting when we go into the next video, and I'll talk through this. 83. 3.10.2 Quote Tool Table Zero Rows Debug: At the end of our last video, I tried to add a line item and we're hitting this error here. And it says subscript out of range. And here's the line that we're hitting an error on. I think I know what's going on here and let me walk through what happened. We have this subroutine here that's adding a line item and we have an issue with this line, which is latest line number. If you go back to the last videos where we created this function and added these lines of code. This is all related to finding our next line number. So we want to find the latest so that we can add one to it for our next number. That basically means we find our latest number in this case, which is one. And then we want to figure out while we're adding a line, what our next number is. So if we added a line, we want to find out our latest was one, our next number is two. And then add our new line item over here. Then if we did it again, we'll have three. So if I run this and hit Add Item, there's three because we find our latest line number which was two, and then increment. What we'd never tested since then is now that we create this clear button. And everything's cleared, we're going to add a line item. And while it's trying to figure out what the latest line number is, it's failing because there are no because there are no lines at all. This is something I mentioned before. I forget if I actually showed it, but if I take Table lines over here, so for example, let me step down here. You have a type mismatch also here. Oh, that's because of all this stuff's blank. So let me fill this out really quick. We have some stuff we need to fix here that make this more user-friendly. We want to catch all these errors. So we're going to start to clean this up. If I step through this code, I'm stepping through here just so I can get this table lines object here. So now that we're halfway running through our code and we've declared our table lines object. We can type instantaneous code here in this window down here. So for example, by type table lines, range dot select, I'm selecting my table. One thing that can be really misleading here is this table looks like it has a blank row. That is only for appearances though. Because if I come down here and type cable lines, a list of rows that count. And actually I can't just run this because this is going to return a number. I need to print this out in a debug print. So if I run this to try to figure out how many rows are in my table, you see the answer is 0, even though it does look like there's one row in here, even though it's blank. This can be really misleading because if I come over here and I hit Spacebar, so I have something here, I can run this again. And you see we now have one row. That's because it looks blank until we add some content here. And even though there's blanks here, this is officially one row of information. So a space character here is the same as if I actually type something in here. And now it realizes there's one row. If I right-click and do delete row, you see the contents gone, but it's still keeps the borders. And that's just because I think it would look funny. If there were no borders over here. It wouldn't look like a table anymore with just the headings. So that is definitely something to keep in mind about list objects and named tables in our Excel sheet is that there are actually 0 rows here, which can look identical to one row of blank information. Now why did I go over that? That's because we find our latest line number by figuring out the content in our bottom-most row, we are hitting an error because as this command over here, He's looking for your bottom-most row of the table. There is no row, so that thing just doesn't exist. That's usually what subscript out of range means. It means that the thing you're looking for doesn't exist. It's like if you have five things in your hand and then somebody asked you, what is the name of the seventh thing you're holding. It says, Hey, we're out of range. We don't have a seventh thing, we only have five things. So that's what's going on here as we're looking for what the last row is, it's telling us that there is no last row. There are no rows in general. How we can handle that is putting an if statement here and saying if Table lines that listeners, just like we have in our immediate window during our demo here, we say dot count, it was 0. Then we're gonna do something. Otherwise, we're going to do what we were doing before. And so basically we're going to say if there's 0 rows, then our latest line number equals 0. Otherwise, if there was a line here that says like one for example, then it will run our typical thing. Our latest line is one, our next line is two. But if I came over here and deleted this row, We're just drag this right back up here. Now, if there's no rows because I just deleted the only rather it was here, then the latest line number is actually 0. And then when we add one to it, our new line number is one. And then we add on new row information here. Because that was just something we overlooked because we had never cleared the entire table before. Our logic that was looking for the next line number was working fine. But when we use our nuclear all function and we are starting from scratch, we now run into this problem, which we have now fixed. 84. 3.10.3 Quote Tool Add Line Validation: Now before I forget, let's go to our next problem that we ran into earlier, which is that we had this being blank and I believe I clicked Add item. And now we have a type mismatch here. Here we're running our subroutine to add a line. And it's saying we have a type mismatch here for our unit price. And that is because when we go to our item unit price over here, we have a value of not found. Here's our unit price over here on the left, which says not found because we don't have any info entered. Meanwhile, our unit price is a variable over here, that's a double. This is indirectly flagging a problem that isn't the root cause. The problem that VBA is flagging here is that unit price is supposed to be a double, but we're trying to put in the value not found into it. So that is a problem, but that's not the real root of our problem. The real root of our problem, of course, is that we don't have any information about the line. And so what we're trying to add this line down to the table down here, it doesn't make any sense. We probably don't want to use or to even be able to do this. So what we should do first, add some validation up here before we start to run this code at all that's trying to get these values and push it down to our grid over here. So what I usually do is run something like create some code for validation up here, we'll say mentioned error message, string. And I've showed you this concept before, the same pattern that I use for flagging error messages. So we'll do it again here. And we'll say if our item field over here, which is our range item number, we can say Keats main ir dot range item number, dot value equals blank. Then we're going to say our error message. We're going to append something to our error message. Error message equals item. Over here. Then underneath, for example, to end our validation, we can say, and then we can add a little break over here, just a comment to break up our code which says validation cleared, had item. And then up here we need to close out our validation logic, which basically says, if there's anything in our error message, meaning it's not blank in our error message. Then we want to end the process and we're going to type issues detected. We're going to create a new line here. And then we're going to show the user or error message. Then I'm even going to create two new line breaks. You'll see how this looks in a second. And add, cannot add line as a new comment. So let's stop this and run this again. I'm going to hit F8. So you can follow the logic here, because item number is blank. Over here on the left, it adds item is blank to our error message string. And then over here for our final check, it says, if error message is not blank, that means we found an error up here. It says issues detected item is blank, cannot add line. Now we can take the same exact code over here. And instead of item number, this is item quantity can change. This quantity will change this to item quantity is blank. I'm going to show you something I'm missing here. What you're going to see, we append our item is blank. We append our item quantity is blank. So we have two different bulleted issues here. And we see this. And what I forgot to do is put a line break between these. And so you see the message doesn't look that great. So I'm going to put a new VB line feed over here. And I'm gonna do the same thing after each bullet. It's going to automatically have a new line. And if I do this again, we add first bullet, the second bullet. And we have item is blank, item quantity is blank, cannot add line. Then we hit this end, which stops the whole macro. And we don't run into are problems where it's trying to work with this data which is invalid to begin with. So we can go ahead and try this. And now we add the line and we don't meet any of these if statements that we've added here. So we don't have any error messages to show and we can continue with our process. So there's our basic fixed for two different issues here. I'm sure we're going to find more as we go and we'll patch them up as we come across them. 85. 4.1.1 UserForm Search Tool - Intro: Hi. So from one of the comments that was asked, if I could do a demo of showing a pop-up user form that can be used to search through data in the spreadsheet. That's what I'm gonna draft through right here. As usual, like my other videos, I'm going to start from scratch and just walk you through everything. It's going to start off a very rough sketch, f first, and then we'll polish it up through the different videos. This is a concept that I use all the time and have many different variations and implementations. So let's get started. We'll talk through some of that as the videos go on. So let's start with example data that we can have here. So maybe I'll just say something like users, I'm going to do Control T here to make a table. My table has headers. It just defaults to having a table name here. We'll just call this table users, let's say. And this could be any dataset. We're just making a name table because in our other videos you see how I use these named tables often for the benefits I've showed before. So I'm just going to say person one. And we'll just drag this down. Let's just have a bunch of people. So there's a large list. What would be common is you have tons of data here that you could even make this even more so much. You can imagine this being hundreds of names that it would be difficult to scroll around and search. So maybe this is why we want to build a pop-up form to make it easy to search through large amounts of data. Now starting from here, we don't have anything, we just have the sheet. What we wanna do is make a pop-up form, which is called a user form. So if I come over here to the Developer and go to View code here. Now we don't have anything. What we can make is if you right-click anywhere in this project explorer over here, you can go to Insert user form. And we have user form one here. So this is just the form in the background. I don't remember if I've used this in any of my other videos yet. So this might be an introduction to it. Let's start with this. If you click here and come down to the Properties, then you can see it's name is user form one. We could change that name, but I'm going to leave it like that for now. You have your caption right here, user form up top. We'll call this search. We'll just call it search. And you see this word up here, change the search. It's called user form one. Let's make this pop up. Now that we just have this user form here, I know it doesn't have anything yet. So if we come back here, let's make it pop up with a button. So we'll insert a button. There's no macro, so we'll just hit cancel here. I'll come back to our macro form and we want to create a module to hold our VBA code. So let's insert a module. We'll say, we'll say launched. Since we have that search form, you can see if I just type, use and hit Control Space to see what the IDE here recommends, you can see it says user form one that exists right here. Then if I hit dot, you can say Show. And now let's attach this button to that macro, launch search form. When I click it, we show our search form. So that's this basic idea of a user form, which is this pop-up form that we can use for different functions. We create this very basic button to just make it show up right there. So let's go back to our search form. When we do a search form, what I'd usually start with and what you might be used to is at the top, we have a text-box. So there's this toolbox where you can put these elements onto the user form. This is a textbox that you could type into. I'm gonna make a little taller here. We'll fix this up later. I'm just going to put some stuff on here to show the concept. And then the next thing I'm going to use is this list box over here. And what this will show is a list of lines that you can select from. So this is just like a text box that you might be familiar with. This won't look that great, but we'll just leave it here. And so we have a text box and a list box. Come over here and click the button and you see we have a pop-up over here. We can type down here. We have a list box, but that doesn't do anything yet. So the first thing you might imagine is we might want to click this button and we want to have a list in here of all of our users. And we can take the users from this data table over here where we have 100 or so names, however many, whatever your dataset really is. How can we populate that info into this list box that isn't doing anything right now. So when you have a user form, it has code behind a user form. So if you right-click and say use, let me go back. So if you right-click and go to View Code, this is the code behind the form, is what is usually called. You can also right-click the form here and goes to go to View code over here. And this says user form clip. There's some stuff that actually this is like a default subroutine it has they're going to have names that VB I just recognizes as basically the events that can happen when you do stuff with the form. And so this is, this is one that's already here, user form click. So if I say Message Box high, e.g. then this should run when it says user form, click, that means the user form. And then when it's clicked, so it's kind of self-explanatory there. Let's try it out. If I click button to, it pops up and then you click on the form and it says high. We come back here. We'll journey back over to where our code is, right-click and view code for the form. So we have this, we actually don't need this subroutine right here. You'll see that user forums, it's kind of older technology and it's got some quirks to it. This just shows up here. Maybe I don't want to use it. Maybe I don't want to coat around just when you click anywhere in the form, which I usually don't. So I'm just going to leave this here for now. I might delete it later to clean things up. The one I want to use is you see this user form object just like we have user form. Click. If you leave this as the user form. And then here's the actions. Like if you select click or double-click, you see it creates this subroutine as if you double-click the user form. And it has this kind of default stuff with it. I don't want that. What I want is user form over here on the left and initialize over here on the right. What this is going to do is it's going to run every time the user form is initialized. So if I click here and click this button, you see before it even initializes, it pops that up. So there's our box and that little subroutines that we had before. Let me go back to our code editor. Every time you come back to the code editor, it comes back to the form. So this is a little cork tear that you always have to go back to the code, user form initialize. It runs this code here. This is where we can put stuff. That happens right when the user form pops up. And this is where we're going to start by pulling in the information from that table of users. If we come back to a user form e.g. or you can click here. And you see this is called text box one. We can rename these, but I'm not going to bother right now. This is called List box one. So we can use that. Let's come back to the code here. And if I start typing list box and hit Control Space, it says list box one. This has properties like add item is what we're going to use. So if I just say add item and I say item here, e.g. in quotations. Now let's go back. That code's going to run when we initialize this form in our first item here is item here. So we'll come back over to this code again. It keeps resetting here and you can do more than once. So this is the concept here where we're going to add items. And now we have two items. Notice it's not going to add the item again. Every time I close the box, it starts over. So I close it and they're all gone. And then it runs those two lines of code and it's going to say item here and item two. And it's not saying here and then 21.2 every single time because every time I close this form and then click this, it's starting a brand new form every single time that pops up. Now we have this table over here. I renamed it the table Users. And we're going to use a concept that we have done in our other videos. So let's dimension this table as a list object. Create a list object. And we're basically going to take that user table and cycle through all of the rows. So all of those person 123 that I've put in there. Now we're going to set the table as that table over there. So set table equals, let's say she's one list objects. We're going to take that table name we have over here. You click over here, it's table users just copying and pasting it lets you see where I'm getting this from. Then we're going to loop through each cell in that table. In this case, we're going to be, in this case we're going to loop through each row of that table. So we're going to say for each list row, which is our L rho object in cable dot listeners. Next L rho. And maybe we'll create a variable here. We'll say dim user. And we'll say user equals L rho dot range. If we did one, that would be the first cell. So we have a row and the first cell of that row, which is really the only cell, is the value. So it's gonna go through each row and take the first cell of each row. If I said range to here, they'll try to take the second cell and it probably error out or maybe do something we don't want it to do. So we've gone over this in the other videos. That's what I'm gonna do here, just as a shortcut for now. So we have each user is going to go through every single row, set the user, and let's add that user to our list box. So we can actually take this up here. And we'll change this text I manually typed to user becoming this variable. Now I can clear this out. And when we launched this thing, it's going to loop through every row of that table and add an item to the list box. We'll click this button. There we go. We have our pop-up with every row on here. And you can see, you can click through here. We have all that data from our table now in this list box. So actually I'm going to stop here. And then in the next step, we're going to build a basic search function where you can narrow down this data by typing text. 86. 4.1.2 UserForm Search Tool - Basic Filter: Picking up where we left off, we have this button here that pops up the search form that now has this list of items that shows all of the data in our name table over here on our spreadsheet. So up to a person 127 here. So you can see it's loading everybody in all the way down to the bottom of this table. The most important function of this thing is that we want to be able to type text up here and then have this information filtered down. And what we'll probably do is make it so that you want to select one of these items in here with the help of this filtering function and put this data somewhere else on your spreadsheet. So that's probably what we're going to end up doing. Now let's start to frame out how that search function is going to work. Again, I'm really making an unpolished form here for now because I want to demo the functions relate. So what we're going to do is go back to our code here. And this is the information that shows all of the stuff in the table because we're looping through every row. Let's make a another function that's going to refresh that data. When we have something in our search box. And now we have to get away from this subroutine that runs just when the form loads, because it only loads once, then we need to interact with the form. The way we can do that at least for now, is I'm going to come back to this form and I'm going to add a button over here, a command button. Let's add this button has some text in here. Let's just call it search. Now if we take this button, it's called command button one. It's kind of running this long button, so let's rename it. Btn search is how it usually name a button like this. And then now if I double-click this button, it automatically frames out this subroutine for us so that you're seeing there's different ways you can create the subroutines in past videos, I'm sure you've seen me type them out. Here. The user form is trying to create the titles of the subroutines that correlate to the actions. We usually call events an event handler. So by double-clicking that button, it realized I probably want to be coding a subroutine. That is when this object button search, since we just renamed it, is clicked. So underscore click and it created this subroutine for us. Just like before. I'll create this message box just to show us here. Forgotten this parentheses. If we come back to our form can click button and click Search is going to run that subroutine. So click this. Let's go back to our code over here. Back on the form because it can happen all the time. Every time you do something, you come back and you're not at the code. I'm back to the code here. So searching. Instead what I wanna do is take the same idea. We use this code when we initialize the forum to bring in all of that information that is from the table. So let's do that again. We know that it's just gonna do the same thing when it initializes. But actually I'll show you something really quick. If you come over here. We have all of our people one through 127. I'm going to click search and it's going to run the same thing. It looks like nothing happened. But we're at one 27th and it starts again. And that's because that code just adds to the list. And then you run it again and it'll add to the list. Again. We're not clearing out any of that information. So if I click this again, we yet have another 127 as it loops through our table here for the third time. Let's come back here. I can even double-click this and it'll bring me over to the same function over here. Because instead of creating this new subroutine, which would be a duplicated that point and those that bring you back over here. So before I do this, I'm going to say list box, just like we use this item over here. List Box dot that clear. So every time we run this, it's going to clear everything before adding all of these items back in from our table data. And the important part here is we don't want to add all of our information back in. We want to filter it down by that textbox that we add it to the top. So let's create a new variable here. We'll call it search. Call it a string. And what we want to search by. Search equals our text box at the top control space again. So text-box one was the name of that text box. Just to remind you, if you click here, it is this word right here is where the name of this textbox object is coming from. If we change this to TXT search, then that's what we're going to want it to be. So if we come back to the code, textbox one actually wanted to make sense anymore. If I do control space, you see it actually won't even recommend text box one anymore because it doesn't exist. Instead I can say text search. Since I renamed that text box object. Then I can say Valley. So search becomes what we enter in that text box at the top. Here is where we're adding all of those users. So instead of going through this loop, so again, this is going to loop through every single row of our spreadsheet table. We don't want to add every single row that it goes through. Instead, as we go through each row, we want to see if that data matches what our searches. So if the user contains what we have in our search box, the string itself, you'll see what I mean as I write this. So what I'm going to say is as we go through every single user one-by-one, we're going to say in string, which I believe I've probably used this in my other videos, which is basically saying inside the user. So in the information in this table over here for person one through whatever, let's say Person 12. Does it contain a substring of search, which is whatever we write inside our text box at the top. So I'll slow that down again so we can see it. And if it's greater than zero, which means if there's any result at all, then that's our if statement. You skipped ahead here I'm going to slow down and just kind of remind us how this string function works. And then only if this condition is met, then we're going to add this user to list. Again, we've cleared out the entire list box, and so it's gonna be blank. And then when we're re-added users, there's gonna be this new criteria. The user has to meet what we have in the search box. So let's see if this works. Let's come back here. One-click button. If we click Search with a blank, Nothing's happening. Really, something is happening. It's clearing out the entire search box and adding everything again. But it looks like nothing's happening. But now if I say type two and click Search, you can see everything has narrowed down here and I'm using letters because I used the same name. You can imagine if this was hundreds of different names, this would be a much more detailed search, but the only thing different between all these numbers, which is why I'm using numbers here. And then if I did three, there you go. And we're filtering everything down. If I type one NO3, there's person 103. I'm going to slow this down really quick. If I come back here, I'm going to just put a breakpoint right here so then we can stop and just look how that function works. Just to clarify here. So as I click this, I'm going to type two and then click search. You'll see the value of our searches. What's in that text box at the top, which is two as I hover over here. So search is two. This is just for the first time going through the first row of the table. So we're actually on person one. What this string is doing is saying within this string, person one, where is the location of the substring? To? Within person one, this string is looking for the stream to and it's not going to find it. And so the answer to this is going to be zero. Now, use this question mark here. I may have shown a debug print in the past. If you do a question mark, that's the same as just showing me what the result of this is, what comes after the question mark. And so the answer that this is zero. And so this saying if the answer to this is greater than zero, then add the user. So as I hit, this gets skipped. Now it's going to loop through again. The user is now person to it saying, where is the search string to? Can you find this within this substring? The answer is gonna be greater than zero. The answer is eight. Because the string, the search string two is the eighth character in the user. Since we pass this criteria, we're going to add the user here. You might even be able to see it happen live. Yeah, so you can see it happen over here. Let's see. It looks like it's not shown that well, as I split this, what you should see here, it's skipping everybody and then probably see Ron user six. When we get to user 12, we should see it show up 11 or 12. And now we're in here again and we're adding the user. So that's what's happening at scale here you can see it happens lightning fast and basically instantaneous for this search result here. And this is how we are getting a filter down search. Type 11, click Search. And you can see with this data, you know there's a bunch of different implementations, but you can have a humongous amount data and it shouldn't happen pretty fast. So this is where you're starting to get hundreds of thousands of lines of information where a person doesn't want to scroll to look for a name, e.g. or whatever the data might be. And if you just type 32 and search, here's all the results. If I type 321 right there, there's our option. 87. 4.1.3 UserForm Search Tool - Select Item: Okay, so building on our previous video, where we have a basic search here, and this filters down all these results from our spreadsheet over here. The last important step for this, and again, this is very unpolished. But the last step of this, just from a general standpoint, is that we want to be able to select one of the items from this list box. So if we filter everything down and now we can more easily find our choice. We want to be able to select this record and probably fill it in somewhere on our spreadsheet. So that's what we'll do next. So we're just going to choose a place. Let's choose any cell here was to sell H5. Just pick a random one over here in the blank space and we can even rename this. We'll call this user selected. Oh, actually, sorry. What I meant to do is type user's selected here. And we'll just use this cell over here on the side. And we'll give this a border so it looks like a field. And I'll change the name here. User selected here with no spaces. It didn't have the right formatting as I was typing this sort of thing in the name. So now this cell is called user selected. And when we hit the search, I'll even change this name right here. We'll get our pop-up and then we want to select one of our selections here that we're able to filter down and have it populate into that cell over there. Now, when we go over to our code, let's see, let me just get to our editor here. I'll go to Developer View code. There's a dozen different ways to get to this editor. I do it differently every time we come back to our user forum. And we need to select one of our items and then submit it. So just for something easy right now, let's put another button on here. And we'll call this button. Select. It might be okay or anything you come up with. So I'm just making it up here. We'll have this button that says Select. Now over here we have command button one-click. So that's what happens when we click that button. Actually, since we named this button search. While we come back to this form, and I will rename this body. So it's not command by the one which is pretty long, will say button. Now, if we double-click this, we create this new. The method over here, the buttons select. This one is still over here, which actually will never get triggered since this button doesn't exist right now. We can just delete that. Again. We'll test it. Selected. I always just like to do this as just a demo that the events work right? If you come over here, you click Search, quickselect, and it says selected, which of course isn't actually doing anything right now. So now we come back to the form. Let's get back to our code. And we need to loop through our list box and figure out what is selected. So this is a one-way or there might be better ways, but this is a simple way that I've done before. And actually there's some syntax and I'm going to forget. So just like before, I think I might just hop into a browser and Google the result and do it in this recording here so we can see it. But I think we're going to loop through all of the items in our list box and figure out which one is selected. That's probably the best way to do it is loop through each item one by one and basically just check when you get to the one that's selected. So let me go ahead and try this out over here. So we'll come over to Google and we'll say VBA from this box selected. So of course I like before, I like to record these into the videos, how I might do a search if I forget something here, I'm just forgetting the syntax. You see, I'm just browsing over here. And just like I suspected, they are doing a loop. So they're looping through the list box. In this case, going through each item of the list box, list box count is how many items are in the list box. And then when they get to an item that is selected. So x is going to go from 01234567 and so forth. If say, item number six is selected, then this statement is going to be true. List box one selected six will be true. And then we'll know that that one is selected. So that's what they're showing here in this example. So let's do that. Let's create a counter. In our example, they were using x in the past. I've just used I as our normal index. Let's do for I equals zero to this box one. I forget if it was item count, list count. I think. Let's come back. Let's count over here and minus one. I believe in my other videos I've gone over how arrays, it depends on the object. I know intuitively, if you haven't done a lot of programming, usually count from 1123 and so forth. But for arrays, in a lot of programming objects, they start at zero. So the first thing is zero and then one, which is why we're going from zero to list count minus one. So e.g. if the list box has three items, this is actually going to say three, like we would intuitively think. But then a counter in the object is going to go item zero, item one, and item two to get your three items. So that's why this notation is here. And they're gonna go, if this box one that's selected, I equals true, then this is whatever this number is. If I say one, then it's going to be, is item one selected true or zero? Since we start at zero, and if the first item is selected, then this will return true. Otherwise it will return false. So that's the example that they're showing us from that. That was actually the Microsoft website. So bring this back to I. And then what they were just shown here is they're just doing a message saying item number. I'm just making a message here for demo selected. And again, remember I is going to be one backwards because zero is the first item. We will see in our example over here. Let's try this out. Let's click our first item and we'll click Select. Item number zero is selected. Item number one is selected. So you see how that's working right there. It is detecting which thing is selected as we loop through. One thing I like to do here is after we find what is selected. Really quick, you see, I'm trying to type in here and it's not letting me, I'm hitting Enter and all that. That's because while this user form is popped up, I can't do anything in Excel, including the editor. So I have to close this and then now I can come back and do stuff with Excel. It's not frozen anymore. We'll come back here. I like to exit the loop. Exit for here once we find what we're looking for, since we're going to loop through all thousand rows basically, once we find the one that's selected. In this case, since we expect only one thing to be selected, then we can just stop looping. So if we find that item three is selected, we don't have to loop through 1,000 more rows. That's unnecessary. So now we have i. What we can do is instead of showing the item number i is selected, I think we can create a variable here just to make it more obvious when I say user string. And when we find the item that is selected, we can get the value of the item that's selected by saying this box. One. Actually let me come back here and we'll just check this. You see it says list box list x. So I believe that is the notation that is going to we were using I instead of x. That's gonna get us our username. So in this same message, faster, we'll put the user, say item. User is selected, instead of just showing the number of the row. So let's come back here and see if this works. Person to, we click Select and user person two is selected. I know this message box doesn't make that much sense. We'll come all the way down. If we change this filter and we do search here, click Select. And we have this. We're detecting the value of the item in the list box that's selected. Now, as you can see, we're getting all the information we need. Let's come back here to our code. Now we don't really need this message box. I just commented this out right here with this apostrophe. I have a hockey to do it. Actually set up a custom thing. But really you can come up here and quick comment or uncommon. Now that we have our value that we're looking for end-user, all we have to do after sheets, one range. And we're going to just say where we want to put this the value. And we've done this tons of times in our other lessons here, we're gonna take the value of user in place it back into the sheet. Here we named this one user selected. If I said I five or whatever this is, whatever the cell address is, that's where this data would go. I'm just going to say, Hey, this cell over here, user place that value there. And then we're going to exit the loop, and that'll be it. I'm going to come over here, select something, click Select. And you see person five ends up in that cell. I can close this. You're probably already thinking that we didn't close that user form. So that's the last thing we can do. After the loop. We can. There's a couple of different ways to do this. Some intuitive way you might think is a user form one dot hide. And that'll close the form. But that's actually only superficially hiding the form to make it disappear, but it might still be active in the background. If you come back to this website, you'll say, you'll see that they write, unload me, which is interesting notation. You might think that's kinda funny. Luckily that sends me right here. This is actually the same as saying unload user form one, which is what we've been referencing our user form. Only this notation of saying me, because this is the code behind the user form. The term me is actually used here to refer to itself. And so that way you could use this notation regardless the name of our user form. So this actually will close out the user form and erase it from memory for the time being and everything, unless you relaunch a new one. So now we can click here. We can type 100 it search, find what we're looking for. Hit Select. And now this field says 100% 100. And of course this would work if you had more realistic data or whatever data source you had. In this case, it could be a specific range. Also doesn't have to be this name table, although I'd like to use these named tables. And there's all sorts of other functions you can build in. But I think at the end of this, this is your bare minimum concept to demonstrate how this would work and will continue to add little cleanup features before we tie this thing out.