Thursday, July 30, 2026

Microsoft Access VBA Class Modules Explained for Beginners

Class modules are one of those Access features that make perfectly capable developers stare at the Create tab and think, "Well, that looks advanced. I'll just pretend it isn't there." The good news is that class modules are not magic, and you do not need to use them to build great Access databases. They are simply another way to organize VBA code when you need it.

The important thing is understanding what class modules are good for, how they differ from standard modules and form code, and when they are just unnecessary complexity. Because, honestly, nobody gets an Access merit badge for turning a simple database into an object-oriented science project.

A standard module is a general container for VBA code. It is where you put public functions, subroutines, constants, declarations, and utility code that can be used throughout the database. You might have a module for email routines, one for date calculations, one for window positioning, or one named GlobalMod that contains common functions used everywhere.

For example, a standard module is a good place for a function that formats a phone number, checks whether a form is open, calculates the next business day, exports a report to PDF, or sends an invoice email. You write the public function once and call it directly from wherever you need it: a form, report, query, macro, or another VBA procedure.

Standard modules are usually the right choice when you have a general-purpose tool. The code performs a task, returns a value, or carries out an action, but it does not need to remember separate information about multiple individual things.

One important detail is that a module-level variable in a standard module is shared during the current Access session. There is one copy of it. It is not automatically separate for each customer, employee, invoice, or form. That is fine for many uses, but it is where class modules can become useful.

A class module is different because it defines a custom object. Think of it as a blueprint. A blueprint is not a house, but you can use it to build multiple houses. Each house can have its own color, occupants, furniture, and questionable decorating decisions, even though they all came from the same plan.

In VBA, the class module is the blueprint. An object created from that class is an instance. If you create a class named CLSEmployee, you can create one employee object for Jim, another for Spock, and another for Susan. Each employee object has its own stored information.

That is the main reason classes exist: they let you work with multiple separate things at the same time, with each thing carrying around its own data and behavior.

An employee class might have properties such as employee name, employee ID, hire date, pay rate, and active status. It might also have methods that perform employee-related work, such as calculating pay, deactivating the employee, or returning a formatted display name.

Properties describe an object. A name, date, amount, status, or ID are all examples of properties. Methods are actions that the object can perform. A method might calculate a total, validate a value, save a record, or display a greeting.

Most class modules keep their actual data in private variables. For example, an employee name might be stored internally in a private variable such as mEmployeeName. Code outside the class cannot directly change that variable. Instead, it has to use the public properties and methods that you expose.

This is called encapsulation, which is just a fancy programmer word for keeping the internal plumbing inside the object. Other code can use the controls you provide, but it cannot climb into the Jefferies tubes and start pulling wires at random.

In VBA, a Property Get procedure retrieves a value, while a Property Let procedure assigns an ordinary value such as text, a number, or a date. So an EmployeeName property can allow outside code to set an employee's name and later retrieve it, while the actual storage remains private inside the class.

There is also Property Set, which is used when assigning an object reference rather than a normal value. If you are assigning a form, recordset, database object, or another custom object, you use Set. If you are assigning text, numbers, dates, or Yes/No values, you use the regular equals sign.

If you have worked with DAO recordsets, you have already used objects and object references. Statements such as setting a database variable to CurrentDb or setting a recordset variable to the result of OpenRecordset are object-oriented VBA, whether you realized it or not.

To use your own class module, you first declare a variable of that class type. For example, you might declare a variable as CLSEmployee. At that point, you have a variable that can hold a reference to an employee object, but you have not created the actual object yet.

To create the object, use the New keyword. In VBA, you would assign the new object reference with Set. Once that is done, you have a fresh employee object in memory, ready to hold its own values.

You could create two employee objects, assign one the name "Jim" and the other the name "Spock," then call a DisplayGreeting method on each one. Each object remembers its own EmployeeName value. They are both built from the same CLSEmployee blueprint, but they are separate instances with separate state.

The full video demonstrates this with a small CLSEmployee class. It contains a private employee-name variable, public Property Let and Property Get procedures, and a simple method that displays a greeting. The point is not that you need a class just to say hello to somebody. That would be using a flamethrower to light a birthday candle. The point is to see how the pieces fit together.

When you are done with an object variable, it is good practice to release it by setting it to Nothing. A simple rule to remember is: if you set it, forget it. VBA often cleans up local objects automatically when a procedure ends, but explicitly releasing object references is a good habit, especially when objects have a longer lifetime or hold other objects internally.

Class modules become more useful when an object has several related pieces of information and several related actions. An employee with a first name, last name, ID, hire date, pay rate, and active status is a reasonable candidate. So is an invoice that contains header information, line items, and a method to calculate its own total.

A customer object might contain customer data along with methods to determine customer status, format a display name, or check discount eligibility. A shopping cart object could add and remove items, calculate tax, and return a total. In each case, the class groups related data and the logic that belongs with it.

Classes can also help when you need multiple separate objects at once. You might have ten invoice objects in memory, each with its own customer, status, line items, and total. With a standard module variable, those values could step on each other. With separate class instances, each invoice keeps its own information.

Another advanced use is reusable behavior across forms. Class modules can respond to events and can be used to manage groups of controls on multiple forms. For example, developers sometimes use classes to apply common button behavior or control events across an application. That is useful, but it can get complicated quickly, so it is not where I recommend beginners start.

Classes also have built-in lifecycle events. Class_Initialize runs when an object is created. It is useful for setting defaults or creating internal objects, such as a collection that the class will use. Class_Terminate runs when the object is being released from memory and can be used for cleanup.

It is worth pointing out that you already work with classes all the time in Access. A form is an object. A report is an object. A text box is an object. A recordset is an object. Access itself is a large collection of objects.

When you write Me.Requery in a form module, you are calling a method on the current form object. When you check Me.Dirty or change Me.Caption, you are working with form properties. When you write code in a form's Before Update event, you are responding to an event raised by that form object.

The code behind a form or report is effectively a class module associated with that particular form or report. It has special access to that object's controls, properties, and events. A standalone class module is simply one you create yourself in the Visual Basic Editor, usually with Insert Class Module.

By convention, I usually begin custom class module names with CLS, such as CLSEmployee or CLSInvoice. You do not have to use that naming convention, but it makes it immediately obvious that you are looking at a class rather than a standard module, form module, or report module.

Do not confuse a class with a table. Your customer information still belongs in a properly designed Customer table. Your invoices, employees, and line items still need proper relationships, keys, and normalization. A class can represent a customer temporarily in VBA memory while your code is working with that customer, but it does not replace relational database design.

That is a beginner mistake worth avoiding: thinking classes are somehow a replacement for tables. They are not. Tables store your data. Classes organize code and temporary in-memory objects. Those are two very different jobs.

For most Access databases, standard modules, form modules, report modules, tables, queries, forms, and reports are more than enough. I have built and taught Access databases for decades, and while class modules have some nifty uses, they are not a requirement for building professional applications.

Use a standard module when you need a general tool. Use a class module when you have a cohesive thing with related data and behavior, especially if you need multiple independent copies of that thing. And if a simple public function does the job cleanly, use the simple public function. There is no prize for making the architecture more complicated than the database needs.

Once you are comfortable with the basics, class modules can do quite a bit more. You can create calculated read-only properties, validate values before accepting them, build objects from table records, manage groups of objects with collections, and create reusable event-handling systems. Those are useful next steps, but there is no need to swallow the whole object-oriented textbook in one bite.

For now, just remember the big picture: a standard module contains shared utility code, while a class module defines a blueprint for objects. Each object instance has its own private state, public properties, and methods. That is all a class really is.

If you want to see the CLSEmployee example built step by step, including creating the class, making two employee objects, setting their properties, and calling their methods, watch the embedded video for the full walkthrough.

Live long and prosper,
RR

Wednesday, July 29, 2026

Can You Answer Why Foreign Keys Go on the Many Side in Microsoft Access? Video Quiz X1.2

Time for a quick Microsoft Access knowledge check. This quiz covers a handful of relational database fundamentals that every intermediate Access developer should know: primary keys, foreign keys, AutoNumbers, lookup values, and unique indexes. These are the little details that keep a database organized instead of turning it into a pile of duplicate data and sadness.

Give yourself a moment to answer each question before checking the explanation. Keep score if you like. No peeking. The database police are watching.

Question 1: What is the main purpose of a primary key in an Access table?

Is it used to uniquely identify each record, store copies of related records, automatically create forms, or sort records alphabetically?

Answer: A primary key uniquely identifies each record in a table.

For example, in a Customer table, each customer should have a unique CustomerID. Two customers might share the same name, city, phone number, or even an email address in some situations, but they should never share the same primary key value.

Primary keys are the foundation of relational database design. They give Access a reliable way to tell one record from another and allow other tables to point back to that specific record. Without a proper key, related data gets messy very quickly.

Question 2: A customer can have many contact records. Where should the CustomerID foreign key normally be stored?

Should it be in the Customer table only, the Contact table, both tables as separate primary keys, or in a report instead of a table?

Answer: The CustomerID foreign key belongs in the Contact table.

This is one of the most important rules in relational database design: in a one-to-many relationship, the foreign key goes on the many side.

One customer may have many contacts. Maybe a company has a billing contact, a shipping contact, a manager, and three people who all insist they are the person you need to talk to. Each of those contact records needs a CustomerID field so Access knows which customer owns that contact.

You would not create CustomerID1, CustomerID2, CustomerID3, and so on in the Customer table. That is a classic beginner mistake. It limits how many related records you can store and makes queries, forms, and reports much more difficult than they need to be.

Question 3: If a primary key is an AutoNumber field, what data type should its matching foreign key usually be?

Short Text, AutoNumber, Long Integer, or Date/Time?

Answer: The foreign key should be a Number field with a field size of Long Integer.

An AutoNumber primary key stores a Long Integer value behind the scenes. Therefore, the matching foreign key must be able to store that same kind of value. In Access, that means setting the related field to Number and choosing Long Integer for its Field Size property.

Do not make the foreign key another AutoNumber. AutoNumber fields generate new values automatically, which is exactly what you do not want in a foreign key. The foreign key needs to store the ID that already exists in the related table.

Question 4: Why is it usually better to store a ShippingMethodID in an order record instead of repeatedly typing the shipping method name?

Do IDs make the table use more columns? Do they avoid inconsistent duplicate names and make changes easier? Can Access not store text in related tables? Or can shipping methods only be used once?

Answer: Using an ID avoids inconsistent duplicate names and makes changes much easier.

Suppose you type shipping methods directly into every order: "UPS Ground," "UPS ground," "UPS-Ground," "UPS," and "That brown truck company." Access sees those as different values, even though they may all mean the same thing.

Instead, create a ShippingMethod table with one record for each method and assign each one a ShippingMethodID. Your Order table stores only that ID. If you later decide to rename "UPS Ground" to something else, you change it once in the ShippingMethod table. Every related order automatically reflects the updated name in your queries, forms, and reports.

That is the whole point of relational design: store a fact once, then relate to it wherever needed. It saves space, prevents typo-related nonsense, and makes maintenance much less painful.

Question 5: What does setting a field's Indexed property to Yes, No Duplicates accomplish?

Does it allow only one blank value, automatically make the field an AutoNumber, prevent two records from having the same field value, or create a relationship with every table?

Answer: It prevents two records from having the same field value.

A unique index is useful when a field should not contain duplicate values, even if it is not the primary key. For example, you may want customer account numbers, employee badge numbers, inventory SKU values, or email addresses to be unique.

Be careful, however. A unique index does not automatically make a field a primary key, and it does not create relationships for you. It simply tells Access, "No two records can have the same value in this field." That can be a very useful rule when the data genuinely needs to be unique.

So, how did you do? If you got all five, congratulations: you have a solid grasp of some of the most important building blocks in Access table design. If you missed a couple, do not worry. Relational design takes a little practice, especially when you are learning where keys belong and why duplicate data causes so many problems.

Watch the embedded video for the full quiz and explanations. These topics, and plenty more relational table fundamentals, are covered in my Access Expert Level 1 class.

Live long and prosper,
RR

Tuesday, July 28, 2026

Can You Answer How Customer Orders Should Be Stored in Microsoft Access? Video Quiz B1.2

Time for a quick Microsoft Access beginner quiz. There are five questions covering some of the most important building blocks of a database: tables, forms, reports, and how customer orders should be stored. Keep track of your answers before checking the explanations.

These are basic concepts, but they matter a lot. Get them right now and your databases will be much easier to build, search, maintain, and expand later. Get them wrong and you may end up with a customer table that looks like someone pressed every button on the TARDIS console.

Question 1: Which Microsoft Access object is primarily used to store the actual data in a database?

Is it a table, form, report, or query?

Answer: A table.

Tables are where the data lives. A customer table stores customer records. An orders table stores order records. A products table stores product records. Everything else in Access is generally designed to help you work with that data in one way or another.

Forms make data easier to enter and view. Queries help you find, filter, calculate, and combine data. Reports format the data for printing or exporting. But the table is the actual storage container.

Question 2: A customer can place many orders. What is the usual relational database design?

A. Put Order1, Order2, and Order3 fields in the customer table.
B. Store each order as a separate record in an orders table.
C. Create a separate customer table for each order.
D. Put all order details in one large notes field.

Answer: B. Store each order as a separate record in an Orders table.

This is one of the most important database design rules to understand. A customer should have one record in the Customer table. Each order placed by that customer should be a separate record in an Orders table.

The Orders table will normally include a field such as CustomerID to identify which customer placed the order. That creates a one-to-many relationship: one customer can have many orders, but each individual order belongs to one customer.

Do not create fields named Order1, Order2, Order3, and so on. That seems tempting when you are first learning, but it falls apart as soon as someone places a fourth order. Customers are not limited to however many order fields you happened to create on a Tuesday afternoon.

Question 3: Why is it often better to store first name and last name in separate fields?

A. Access requires all names to be split into two fields.
B. It makes sorting, filtering, and personalized letters easier.
C. It prevents two customers from having the same last name.
D. It automatically creates a primary key.

Answer: B. It makes sorting, filtering, and personalized letters easier.

Access does not require names to be split. You certainly can keep a full name in one field if that is all you need. But separate FirstName and LastName fields give you more flexibility.

You can sort by last name, filter for everyone named Smith, or create personalized correspondence that says, "Dear Spock," instead of "Dear Spock Smith." Separate fields also make it easier to create mailing labels, reports, and queries later.

It does not stop duplicate last names, and it has nothing to do with automatically creating a primary key. Plenty of people can share the same last name. That is why we use an ID field to uniquely identify records.

Question 4: Which Access object is generally best for entering and viewing data on the screen?

Would that be a table, form, report, or relationship?

Answer: A form.

You can enter data directly into a table, especially while you are building and testing your database. But for day-to-day use, forms are generally the better choice.

A form lets you control what users see, arrange fields in a sensible layout, add buttons, limit mistakes, and keep people out of fields they should not be touching. Tables are for storing data. Forms are for working with it on the screen.

Question 5: Which Access object is generally designed for formatted printing, such as invoices or mailing labels?

Answer: A report.

Reports are designed for printouts, PDFs, invoices, labels, summaries, and other formatted output. You can make reports look professional, group records, add totals, include logos, and control exactly how information appears on the page.

Remember the simple rule: forms are for the screen, reports are for printouts. There are exceptions, of course, because this is Access and there is almost always an exception somewhere. But that rule will serve beginners very well.

How did you do? If you got all five correct, congratulations. If you missed a few, no worries. These topics, along with much more beginner-level Access training, are covered in Access Beginner 1, Lesson 2. Watch the embedded video for the quiz and explanations, then see if you can score a perfect five out of five next time.

Live long and prosper,
RR

Wednesday, July 22, 2026

Why Microsoft Windows, Excel, and Access Change 1940 to 2040: Adjust the 2-Digit Year Cutoff

Have you ever entered a date such as 11/40 in Excel or Microsoft Access, only to have it turn into January 1, 2040? That is especially annoying when you are entering birth dates, genealogy records, cemetery information, or any other historical data where 1940 is a whole lot more likely than 2040. The problem is not that Excel or Access is broken. It is how Windows interprets two-digit years.

A two-digit year is ambiguous by definition. When you type 35, does that mean 1935, 2035, or perhaps 2435 if you are entering dates aboard the Enterprise? Windows has to make an assumption, so it uses something called a two-digit year cutoff. Once you understand that cutoff, you can change it when it makes sense for your work.

With the common current Windows setting, years from 00 through 49 are interpreted as 2000 through 2049. Years from 50 through 99 are interpreted as 1950 through 1999.

So if you enter 11/40, Windows assumes you mean 2040. Enter 11/72, however, and Windows assumes 1972. The computer is not trying to mess with you. It just has to draw the line somewhere, and by default it assumes that lower two-digit years are probably future dates or relatively recent dates.

This is important because it is generally not an Excel setting or an Access setting. Both programs rely on Windows to help interpret dates typed in using two-digit years. That is why the same date entry can behave the same way in Excel, Access, and other Windows-aware applications.

For the average person entering invoice dates, appointments, warranties, due dates, schedules, and other business records, the default behavior makes sense. If someone types 35, they probably mean 2035, not 1935. But if you work in a doctor's office, deal with geriatric patients, maintain historical records, work for a genealogist, or manage a cemetery database, that assumption can be completely backwards.

Fortunately, you can adjust the cutoff in Windows. Open the Control Panel, go to Clock and Region, then select Region. Click Additional Settings, open the Date tab, and look for the setting labeled When a two digit year is entered, interpret a year between.

For example, if you change the cutoff to 2029, then two-digit years from 00 through 29 will be treated as 2000 through 2029. Years from 30 through 99 will be interpreted as 1930 through 1999. After making that change, entering 11/30 will produce a date in 1930 instead of 2030.

That can save a lot of frustration if you regularly enter dates from the 1930s and 1940s. Once the setting is changed, Excel and Access should immediately follow the new Windows interpretation. You do not need to hunt through both programs looking for separate date settings, because there usually are not any to change for this particular behavior.

If you need to change this setting on several computers, there is a handy shortcut. Press Windows-R to open the Run dialog, type intl.cpl, and press Enter. That opens the Region settings directly, saving you a few clicks. It is not something most people need every day, but it is useful if you are setting up a group of workstations for a medical office or historical data-entry project.

There is one big caution: changing the Windows cutoff affects how two-digit years are interpreted across the computer. That may be exactly what you want, but it also means someone entering an appointment date of 11/35 might now get 1935 instead of 2035. Pick a cutoff that makes sense for the type of data your users enter most often.

Personally, the best solution is still to avoid two-digit years whenever possible. Type the full four-digit year. Better yet, use the ISO date format: YYYY-MM-DD. For example, 1940-11-01 is completely unambiguous. It does not depend on a Windows cutoff, it does not depend on regional date formats, and it does not make the computer guess what century you meant.

In an Access application, you can also take this a step further. Rather than changing the Windows setting for every user, an Access developer can create a reusable function that applies a custom cutoff only where it is needed, such as a Date of Birth field. That lets the application control the interpretation without affecting order dates, invoice dates, or other fields that may need a different assumption. The full implementation and demonstration are included in the embedded video.

So if 1940 keeps becoming 2040, now you know why. Windows is applying its two-digit year cutoff, and Excel and Access are following along. Change the cutoff if your work calls for it, but whenever you can, enter all four digits of the year and eliminate the ambiguity entirely.

You can watch the embedded video for the full walkthrough and a live demonstration in both Excel and Microsoft Access.

Live long and prosper,
RR

Tuesday, July 21, 2026

How to Connect Microsoft Access to SQL Server Online (Step-by-Step Tutorial)

Getting your Microsoft Access database connected to SQL Server so you can use it online (and work from literally anywhere with an internet connection) is way easier than most people think. If you're picturing a process full of pain and technical headaches, you're about to be pleasantly surprised.

This guide walks you straight through the steps to move your Access tables to SQL Server, set up all the necessary connections, and have your database online in no time. There are some tools and options along the way, but I'll show you my favorite methods and point out the stuff to watch for so you don't fall into the typical gotchas.

So, here's the big picture: we're going to make your Access database talk to SQL Server, specifically an online, hosted SQL Server (not just something stuck on your office PC). Once your data's up there, you can work remotely, collaborate, and even set things up for web access down the road.

First things first - you need SQL Server Management Studio, or SSMS for short. This is Microsoft's free tool for working directly with your SQL Server database. You don't need to install the full SQL Server engine (unless you want to play with it locally - SQL Server Express works for that), just SSMS to manage your online server. Do a quick web search for "SQL Server Management Studio" - make sure you're grabbing it from Microsoft's website - and get it installed. It's painless, just a few clicks, and it'll be your go-to for working with your remote database.

Once you've got SSMS installed, you'll log in using the server address and credentials you got from your hosting provider (for example, Winhost). Remember, the server name is basically your data source, and authentication is going to be SQL Server authentication rather than Windows. Jot all of that info somewhere handy, because you'll use it a bunch.

After logging in, you'll see your database shell sitting on the server side. Maybe it's empty for now - or maybe you already poked in some test stuff. Either way, don't worry about all the extra bells and whistles in SSMS for now. We're just going to move tables and verify our data is there.

Now, a lot of ISPs offer their own control panels for adding databases and tables, but honestly, SSMS is a thousand times easier and more dependable. If you want to skip frustration, just stick with SSMS.

The next step is creating an "ODBC" connection so Access and SQL Server can talk to each other. ODBC sounds scarier than it is. Basically, it's a translator. You set it up using a "DSN" file - a Data Source Name file - that stores the connection info. There are two types: machine data sources (stuck to one computer) and file data sources (which can be moved around and shared). I like file data sources; they're portable and flexible, especially if you're not the only one who needs access.

To create your DSN file, in Access, go to External Data, New Data Source, and pick ODBC Database. Choose to link (not import), then hit "New" to create a file data source. Choose SQL Server from the long list, give it a name, and then set the server address (the one from your host). Authentication will be SQL Server authentication, so use your username and password as before. Set the database you want to use (again, from your host details), finish the wizard, and test the connection. If you get a "test completed successfully" message: you're golden. If not, double-check those passwords - typos happen to all of us.

Next up is actually getting your Access tables up to the server. There's an official Microsoft tool called the SQL Server Migration Assistant for Access. If you have a ton of tables, it can help, but I've had some headaches with it missing stuff. Honestly, I prefer to do things manually - export table by table - which gives you more control and fewer surprises.

So, pick a table in Access (like your customers table), right-click it, go to Export, then ODBC Database. Choose your new DSN file as the target. You'll have to enter your password again (it's a recurring theme), and Access will move your table up to SQL Server. Want to double-check? Head back to SSMS, refresh your tables, and you should see the new table (named with "dbo." in front - don't worry, that's normal) sitting there in your database.

Now for the magic part: linking Access back to the new SQL Server version of your table so everything works like it always has - just with the data now online. In Access, delete the old local table (chill, you've got a copy on SQL Server now), then go to External Data, ODBC Database, and link again using your DSN file. Select the SQL Server table (it'll have the "dbo." prefix), and Access will ask which field is your unique record identifier - select your primary key. Decide if you want to save the password (if you do, anyone with this front-end can open it; just something to keep in mind for security). Now you've got a linked table in Access pointing to your table on SQL Server. You can even rename it back to the original table name so your forms and reports don't skip a beat.

Fire up your forms - you'll notice that everything works just as before, except now your data's coming from the cloud. You might see a hair more delay if you're pulling big lists, but we'll get into optimizing that in future lessons. For most everyday uses, it's perfectly snappy.

One quick tip: if you're looking to get more performance or work with big data sets, learning the SQL language is a must. SQL Server's query language will let you do all sorts of powerful things directly on the server and speed up your apps. (Yes, I've got full seminars on that, so don't worry about having to learn it all at once.)

And that's basically it! You've connected Access to SQL Server online, exported your data, and set up the links so Access just thinks it's working with regular tables - except now you can do it anywhere and you're set for much bigger, better things down the road.

If you want to see all these steps in action, watch the embedded video above for the full walkthrough, including some extra tips and the inevitable tangent or two. Happy databasing!

Live long and prosper,
RR

Monday, July 20, 2026

Microsoft Access Video Quiz 2: Relational Databases, Table Relationships, Junction Tables & More!

Relational database design is one of those topics that seems simple at first, right up until you put customer names, phone numbers, addresses, vehicles, orders, and three copies of the same information into one giant table. Then things get ugly fast. This quiz will test the core ideas behind relational databases, table relationships, and junction tables.

Give each question a moment before looking at the answer. Keep score if you like. If you get all five correct, congratulations: you may keep your database designer badge. If not, no worries. These are foundational concepts, and getting them right will save you a whole lot of headaches later.

Question 1: What is a relational database?

A) Tables connected by relationships
B) A database with one table
C) A spreadsheet with worksheets
D) A database on the internet

Answer: A) Tables connected by relationships.

A relational database is built from separate tables that are connected using relationships. Instead of cramming customers, vehicles, repairs, invoices, and payments into one mega-table from the depths of database despair, you store each type of information in its own appropriate table.

For example, you might have a Customer table and a Vehicle table. The Customer table stores information about people. The Vehicle table stores information about cars. A relationship tells Access which customer owns which vehicle. That is the basic idea behind a relational database, and it is a huge part of what makes Access useful.

Question 2: What does the Vehicle table use to identify the owner of the vehicle?

A) The customer name
B) The customer ID
C) The customer's address
D) The customer's phone number

Answer: B) The customer ID.

The Vehicle table should store the CustomerID, not the customer's name, address, or phone number. Those details belong in the Customer table.

Why? Because names can be misspelled, changed, duplicated, or entered differently by different people. "Joe Smith," "Joseph Smith," and "J. Smith" might all be the same person, but Access has no magical mind-reading function. A CustomerID is unique and consistent. It gives every customer one reliable identity in your database.

Once the Vehicle table has the CustomerID, you can use a query, form, or report to pull in the customer's name and other details whenever you need them. Store the information once, then look it up. That is the whole point.

Question 3: Joe Smith buys a second car. What is the best design?

A) Add another Joe Smith record
B) Store Joe once and link both cars
C) Create a new customer table
D) Put both cars in one field

Answer: B) Store Joe once and link both cars.

Joe belongs in the Customer table one time. If he owns two cars, each car gets its own record in the Vehicle table, and both vehicle records use Joe's CustomerID.

Creating duplicate customer records is one of the classic beginner mistakes. It works for about five minutes, until Joe changes his phone number and you update one record but forget the other. Now your database has conflicting information, and nobody knows which phone number is correct. That is how databases become haunted.

Likewise, do not put multiple cars in one field. A field should hold one piece of information, not a shopping list. Keep each vehicle in its own record. That makes searching, sorting, reporting, and maintaining the data much easier.

Question 4: Customers and orders usually have what kind of relationship?

A) One-to-one
B) One-to-many
C) Many-to-many
D) A self-join

Answer: B) One-to-many.

A customer can place many orders over time. However, each individual order normally belongs to one customer. That makes the relationship between Customers and Orders a one-to-many relationship.

In Access terms, the Customer table is on the "one" side, and the Order table is on the "many" side. The Order table contains a CustomerID field that points back to the customer who placed that order.

This is probably the most common relationship type you will use in a real-world database. One customer can have many orders. One customer can have many vehicles. One customer can have many appointments, invoices, payments, notes, or whatever else your business needs to track.

Question 5: What relationship uses a junction table?

A) One-to-one
B) One-to-many
C) Many-to-many
D) Parent-to-child

Answer: C) Many-to-many.

A many-to-many relationship exists when records on both sides can relate to multiple records on the other side. For example, suppose one driver can drive several vehicles, but each vehicle can also be driven by several different drivers. You cannot handle that cleanly with just a Customer table and a Vehicle table.

That is where a junction table comes in. You might create a DriverVehicle table containing a DriverID and a VehicleID. Each record in that table represents one specific connection between one driver and one vehicle.

The junction table turns one many-to-many relationship into two one-to-many relationships. One driver can have many records in the junction table, and one vehicle can also have many records in the junction table. It may sound a little strange at first, but once you understand it, junction tables become one of the most useful tools in relational database design.

So, how did you do? If you got all five, you have a solid handle on the basics of relational database design. If you missed a few, that is exactly why quizzes like this are useful. Relationships, primary keys, foreign keys, and junction tables are not just theory. They are what keep your Access database organized, accurate, and much easier to maintain.

Watch the embedded video for the full quiz and a quick walkthrough of each answer.

Live long and prosper,
RR

Thursday, July 16, 2026

Microsoft Access Database Is Read Only? Here's How to Fix It. Common Causes

There's nothing quite like the moment you fire up your Microsoft Access database only to find out it's suddenly read only and you can't save any changes. Maybe you were happily updating customer records yesterday, and today? Nada. No design changes. No new data. Before you start sweating, let's chat - most of these issues are fixable without any drama.

First things first, let's talk about what "read only" really means in Access. The program's not saying your database is broken; it's just putting up a "look, don't touch" sign. The important bit is figuring out why it did that... and that's what we'll get into here.

So, let's walk through the most common reasons your Access database turns read only, starting with the easy (and sometimes embarrassing) ones and working toward the weirder stuff.

Step one: Did you actually open it in read only mode? It sounds silly, but Access sometimes just does what you tell it - even if you didn't mean it. If you opened the database using File > Open, check the little drop-down next to the Open button. There's Open Read Only in there, and it's shockingly easy to click the wrong option. Happens to the best of us. Just make sure you actually opened the database normally before we start blaming Windows or the database file itself.

If that's not it, the next culprit is Windows marking the file as read only. Go to File Explorer, right-click on your actual database file (not a shortcut), and hit Properties. Down at the bottom, look for Attributes. If "Read Only" is checked, clear it and Apply. Also, if you see a message saying "This file came from another computer and might be blocked," hit Unblock. That sometimes happens if you downloaded the database or opened it from an email attachment - good old Windows security at work.

Still locked out? Try copying the database to a different location on your computer, like your Desktop, and see if you can work with it there. If that works, you might have a folder permission problem, which is especially common for databases stored on a network share. Here's a big tip: Access requires permission to create a little companion file (the .LACCDB "lock file") in the same folder as your database. If it can't create or update this file, Access plays it safe and goes read only. To fix this, make sure you have full read-write access to the folder - not just the file. If you're on a business network, you might need your IT folks' help for this one.

Another fun curveball: is someone else using the database in exclusive mode? Access likes to let lots of people use the database at the same time, but if one person opens it "exclusive," everyone else gets blocked. Sometimes it's not even Access itself but another program - like Excel linked to your database, backup software, or those annoying cloud sync services (looking at you, OneDrive, Google Drive, Dropbox) - that hijacks your file. That's why it's a terrible idea to actually use Access out of a cloud-synced folder. Backup? Yes. Live database work? Never.

If things are still weird, you could be dealing with a stuck lock file (.LACCDB or .LDB for those still on ancient versions). Normally Access creates this lock file when the database is open and deletes it when the last person signs out. But if Access or Windows crashes, that file can get left behind - and Access gets confused and stubborn. If you find a lock file in the same folder as your database but you know for a fact that everyone is out of the database, you can delete it manually. Just double and triple check - deleting it while someone is still in the database is a recipe for trouble.

Now, here's one that sneaks up on people - the file extension. If your database ends in .ACCDB, life is good. That's a normal, editable database file. If it ends in .ACCDE, that's a compiled, "execute only" version. Developers use this to lock things down. With an .ACCDE, you can edit data, but design changes (tables, queries, forms, VBA code) are locked out by design. If you need to make design edits, you'll need the original .ACCDB file from the developer. For everyday data entry though, .ACCDE shouldn't stop you.

Still no luck? Try using Compact and Repair from inside Access. This can sweep up minor database corruption and clear out the cobwebs. Trust me, always back up before you do this - and frankly, you should have a solid nightly backup strategy regardless. Restoring a backup is way easier than pulling a mangled database back from the dead.

If your database is split (you're using linked tables), remember: the problem might not be in your front-end file. If you don't have permission to the folder where the back-end lives, Access can get cranky and start acting up. Always check that you can browse to that backend file and that you have read-write access there, too.

And finally: if all else fails, try creating a brand new blank Access database and import all your objects from the old one. Sometimes it's the database file container itself that's got gremlins. Import objects one at a time to reduce the chance of dragging some corruption along for the ride. Again - backups, backups, backups. I can't say it enough.

Quick recap checklist for the next time your database opens read only:

* Did you accidentally open it as read only?
* Is the file marked read only or blocked by Windows?
* Are folder permissions causing trouble?
* Anyone else hogging the database in exclusive mode?
* Is there a stuck lock file hanging around?
* Is the file actually an .ACCDE?
* Tried compact and repair yet?
* Considered importing into a new file?
* (And don't forget: sometimes your antivirus can block Access files too!)

Usually, if Access says "read only" it's being cautious, not broken. It's often just looking out for your data. So don't panic - work through the list, and you'll be back to editing in no time.

For all the nitty-gritty details, walkthroughs, and extra geeky bits, check out the video embedded above.

Live long and prosper,
RR