Contractor Talk - Professional Construction and Remodeling Forum banner

Microsoft access 2010

9754 Views 104 Replies 10 Participants Last post by  smalpierre
Finally broke down & got a laptop...

Anyone got any pointers for this program? Seems like it has potential to link customers to jobs & jobs to customer specific "products"

Example: I bid an apartment complex interior repaint based on various floor plans. So each customer has roughly 4-8 specific "products" where the price is unique to that customer.

I would also like to link to what person worked on that individual product. This way I can click on the employees name & see a history of all jobs he ever did.
21 - 40 of 105 Posts
Customers table, Products table, and a join table - name it something like Invoice_Lines table. Invoices_Lines holds foreign keys for Customers and Products. Customers and Products each have a primary key named the same as the foreign key for them that is in the Invoices_Lines table. Then go to the graph screen and drag from Customers primary key to the same name in Invoices_Lines. Then drag from Products primary key to the foreign key in Invoices_Lines named the same. That forms the basis for your relationship. You put all the Customer name, address, zip code, phone and so forth fields in Customers table, and the names for your finished 'PRODUCTS' in the products table. Do your reports based on Invoice_Lines table.
Use autoincrement fields for the primary keys. Saves a lot of problems later. If you use customer name and you try to insert a second "john smith" it will fail. Also when you're doing lookups in a many to many table it's a lot less work for the computer to compare than text string comparison - among other issues it solves.

You COULD use a composite key, but that introduces it's own problems and doesn't 100% solve the original one.

Also you want to break customer contact info out into it's own table so you can store multiple phone numbers for a single contact for example. You COULD have two phone number fields but what if a customer has 3? You could put 3 in there - but then for each customer you're storing the data space for 3 phone numbers when most only have 1 ...

This falls under database normalization which is a technique to prevent data anomalies. Sometimes though, it can be overdone to the point of extreme complexity when it should be a tool to make it more simple.

Assume you have customers which can be consumers or businesses:

http://dba.stackexchange.com/questions/41427/database-design-people-and-organisations
See less See more
This is kind of what you want. Extremely oversimplified and limiting in a lot of ways, but it's a start.

I'll post the SQL create script (from MySql) and give you some sql to start with - how to insert, update, delete, and most importantly select and filter the data in SQL. You'll have to modify it probably for Access.

Text Line Screenshot Parallel Font
See less See more
Full working MySql create script:

SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0;

SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;

SET @[email protected]@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';



CREATE TABLE IF NOT EXISTS `test`.`company` (

`CompanyId` INT(11) NOT NULL AUTO_INCREMENT ,

`CompanyName` VARCHAR(45) NOT NULL ,

`Street` VARCHAR(45) NOT NULL ,

`City` VARCHAR(45) NOT NULL ,

`State` VARCHAR(2) NOT NULL ,

`Zip` INT(5) NOT NULL ,

PRIMARY KEY (`CompanyId`) )

ENGINE = InnoDB

DEFAULT CHARACTER SET = latin1

COLLATE = latin1_swedish_ci;



CREATE TABLE IF NOT EXISTS `test`.`company_has_contacts` (

`Company_CompanyId` INT(11) NOT NULL ,

`Contacts_ContactId` INT(11) NOT NULL ,

PRIMARY KEY (`Company_CompanyId`, `Contacts_ContactId`) ,

INDEX `fk_Company_has_Contacts_Contacts1_idx` (`Contacts_ContactId` ASC) ,

INDEX `fk_Company_has_Contacts_Company_idx` (`Company_CompanyId` ASC) ,

CONSTRAINT `fk_Company_has_Contacts_Company`

FOREIGN KEY (`Company_CompanyId` )

REFERENCES `test`.`company` (`CompanyId` )

ON DELETE NO ACTION

ON UPDATE NO ACTION,

CONSTRAINT `fk_Company_has_Contacts_Contacts1`

FOREIGN KEY (`Contacts_ContactId` )

REFERENCES `test`.`contacts` (`ContactId` )

ON DELETE NO ACTION

ON UPDATE NO ACTION)

ENGINE = InnoDB

DEFAULT CHARACTER SET = latin1

COLLATE = latin1_swedish_ci;



CREATE TABLE IF NOT EXISTS `test`.`contacts` (

`ContactId` INT(11) NOT NULL AUTO_INCREMENT ,

`Position` VARCHAR(45) NOT NULL ,

`FirstName` VARCHAR(45) NOT NULL ,

`LastName` VARCHAR(45) NOT NULL ,

`OfficePhone` VARCHAR(45) NULL DEFAULT NULL ,

`CellPhone` VARCHAR(45) NULL DEFAULT NULL ,

`Email` VARCHAR(45) NULL DEFAULT NULL ,

PRIMARY KEY (`ContactId`) )

ENGINE = InnoDB

DEFAULT CHARACTER SET = latin1

COLLATE = latin1_swedish_ci;



CREATE TABLE IF NOT EXISTS `test`.`floorplans` (

`FloorplanId` INT(11) NOT NULL AUTO_INCREMENT ,

`CompanyId` INT(11) NOT NULL ,

`UnitName` VARCHAR(45) NULL DEFAULT NULL ,

`SquareFeet` INT(11) NOT NULL ,

`Bedrooms` INT(11) NOT NULL ,

`ListPrice` DECIMAL(7,2) NOT NULL ,

`Description` TEXT NOT NULL ,

PRIMARY KEY (`FloorplanId`, `CompanyId`) ,

INDEX `fk_Floorplans_Company1_idx` (`CompanyId` ASC) ,

CONSTRAINT `fk_Floorplans_Company1`

FOREIGN KEY (`CompanyId` )

REFERENCES `test`.`company` (`CompanyId` )

ON DELETE NO ACTION

ON UPDATE NO ACTION)

ENGINE = InnoDB

DEFAULT CHARACTER SET = latin1

COLLATE = latin1_swedish_ci;



CREATE TABLE IF NOT EXISTS `test`.`installers` (

`InstallerId` INT(11) NOT NULL AUTO_INCREMENT ,

`InstallerName` VARCHAR(45) NOT NULL ,

PRIMARY KEY (`InstallerId`) )

ENGINE = InnoDB

DEFAULT CHARACTER SET = latin1

COLLATE = latin1_swedish_ci;



CREATE TABLE IF NOT EXISTS `test`.`salesorders` (

`SalesOrderId` INT(11) NOT NULL AUTO_INCREMENT ,

`FloorplanId` INT(11) NOT NULL ,

`InstallAddress` VARCHAR(200) NOT NULL ,

`SalePrice` DECIMAL(7,2) NOT NULL ,

`InstallerId` INT(11) NULL DEFAULT NULL ,

`OrderDate` DATETIME NOT NULL ,

`InstallDateReq` DATETIME NOT NULL ,

`InstallComplete` DATETIME NULL DEFAULT NULL ,

`Paid` TINYINT(1) NOT NULL DEFAULT '0' ,

PRIMARY KEY (`SalesOrderId`, `FloorplanId`) ,

INDEX `fk_SalesOrders_Floorplans1_idx` (`FloorplanId` ASC) ,

INDEX `fk_SalesOrders_Installers1_idx` (`InstallerId` ASC) ,

CONSTRAINT `fk_SalesOrders_Floorplans1`

FOREIGN KEY (`FloorplanId` )

REFERENCES `test`.`floorplans` (`FloorplanId` )

ON DELETE NO ACTION

ON UPDATE NO ACTION,

CONSTRAINT `fk_SalesOrders_Installers1`

FOREIGN KEY (`InstallerId` )

REFERENCES `test`.`installers` (`InstallerId` )

ON DELETE NO ACTION

ON UPDATE NO ACTION)

ENGINE = InnoDB

DEFAULT CHARACTER SET = latin1

COLLATE = latin1_swedish_ci;





SET [email protected]_SQL_MODE;

SET [email protected]_FOREIGN_KEY_CHECKS;

SET [email protected]_UNIQUE_CHECKS;
See less See more
I have quickbooks pro as well.

I didnt find what I wanted in it. I service apartment complexes. So each customer will have a unique set of services used repeatedly. For example: Customer one will have riughly 12 products, invoiced multiple times over the year.

Couple that with an all new service I am starting next month, where I will have tech's doing work, and well...

I am paperless. I want my tech to log in, record jobsite, hours, service performed, generate an invoice, as well as an inventory restocking list.
I have quickbooks pro as well.

I didnt find what I wanted in it. I service apartment complexes. So each customer will have a unique set of services used repeatedly. For example: Customer one will have riughly 12 products, invoiced multiple times over the year.

Couple that with an all new service I am starting next month, where I will have tech's doing work, and well...

I am paperless. I want my tech to log in, record jobsite, hours, service performed, generate an invoice, as well as an inventory restocking list.
You can do it in quickbooks, not exactly sure how you'd go about setting up customer specific products but I'm sure you can.

The premeir contractor version has all the cool reports and all that. I think in pro you'd have to build your own. Anyway - when I get back from my day job, I'll trim down that create database sql so it'll be more portable, and whip out a few queries for ya.
I'll check out sql. Thanks man. This is kinda just a pet project. So theres no real hurry.
Use autoincrement fields for the primary keys. Saves a lot of problems later. If you use customer name and you try to insert a second "john smith" it will fail. Also when you're doing lookups in a many to many table it's a lot less work for the computer to compare than text string comparison - among other issues it solves.

You COULD use a composite key, but that introduces it's own problems and doesn't 100% solve the original one.

Also you want to break customer contact info out into it's own table so you can store multiple phone numbers for a single contact for example. You COULD have two phone number fields but what if a customer has 3? You could put 3 in there - but then for each customer you're storing the data space for 3 phone numbers when most only have 1 ...

This falls under database normalization which is a technique to prevent data anomalies. Sometimes though, it can be overdone to the point of extreme complexity when it should be a tool to make it more simple.

Assume you have customers which can be consumers or businesses:

http://dba.stackexchange.com/questions/41427/database-design-people-and-organisations
I always use an autoincrementing number field that does not allow any user to input for my Primary fields. I also put timestamp, user, user modification stamp fields into every table, but that is getting much deeper than what I felt was a basic explanation of setting up tables and relationships. Filemaker is truly way more flexible than all other database creation programming interfaces, - primary keys are actually not required, it will still work fine and perform as a relational database without them, but just about nobody I know ever built a solution that didn't utilize primary and foreign keys or follow data normalization rules.
I remember when Access 97 came out I had a book with some nice tutorials and learned how to do stuff like you explained through tables and reports pretty easily. The last time I checked out Access 2010, every manual I stuck my nose in was garbage, no tutorials just instructions trying to explain what every function does. Everyone wants you to learn with Youtube now a days which I find really limiting. To my understanding, SQL is a more powerful database in that it can handle thousands of users more efficiently than Access could. That's something a contractor doesn't need because the only user is you. But you might try the MySQL before you go too far with Access and frustrate yourself.
I just looked at MySql, $2,000 for one year of use? I would find a different way to track who painted a house. Maybe stick with Access or even Excel might have a function to do that.
I just looked at MySql, $2,000 for one year of use? I would find a different way to track who painted a house. Maybe stick with Access or even Excel might have a function to do that.
MySQL is open source and free. The enterprise version is how open source companies make their money.

Driftweed, Why not just use LibreOffice's Base program http://www.libreoffice.org/discover/base/ not only will if create a db it will also interface as a frontend with MySql and it forks. It will also access the rest of the LO suite.

I have never used base but LO suite is my goto for office programs.
SQL of one form or another sits at the back of almost all relational databases. There are numerous versions. SQLITE is another free open source version besides the open source MYSQL. The thing is that with the bulk of them you still have to create a front end gui to display the data in a presentable form, and also you need to create reports and setup for printing. Programs like Access and Filemaker do all the front end lifting for you if a basic looking front end is all you want. Both have capability to extend that far beyond the simple, just as how all the spreadsheet programs will allow advanced formulae to be utilized in making a real deal spreadsheet program. Relational Databases kill the hell out of spreadsheets in usability and reporting however. And when done right there is only one place to enter data, and no repeating of any input. For simplicity though, you cannot beat Filemaker. An independent but fully owned by Apple company. What is best about it is you can create a full database applications for use on Ipads and Iphone without having to run your app thru approval and paying Apple 1/3 of selling price at the Apple Store when you market them. Anybody who has put an app thru the app store process knows what a trial that can be. I can sell apps (albeit without the exposure that the app store can provide..) at the price I decide, and the content I choose.
That is the best part about it.
See less See more
There's a ton of them out there, MySql being the most prolific. I've used everything from Access to Oracle, and MySql is my favorite by a long shot - although I'm not a fan at all of the MyISAM table type that most MySql databases are made with.

Mostly people use MyISAM because at one time it was a lot faster. The main problem I have with it is the lack of foreign keys - you cannot link tables together so your front end code has to handle data integrity.

It's not really that much faster anymore. If you're building a website with millions of requests / day it's still not really that much more efficient. I think it's silly to give up one of the cornerstones of a relational database for a marginal speed increase, ESPECIALLY when I see horrible front end code that's slow as molasses, and written with Java or some other resource hog like Ruby on Rails, or some bloated PHP framework.
I just looked at MySql, $2,000 for one year of use? I would find a different way to track who painted a house. Maybe stick with Access or even Excel might have a function to do that.
That's mostly for things like tech support which a lot of organizations seem to think are necessary in case the developers run into problems that they don't know how to resolve.

For most issues, internet discussion boards are more than adequate - but if you're a bank, and there's billions of dollars worth of transactions crossing the database - it's a bit of added insurance that problems can and will be dealt with.
For most issues, internet discussion boards are more than adequate - but if you're a bank, and there's billions of dollars worth of transactions crossing the database - it's a bit of added insurance that problems can and will be dealt with.
:rolleyes:Really banks use enterprise Mysql...

Good lord :laughing: I hope the people designing the software and banking systems are smart enough to program in SQL all by themselves, without having to ask questions. Maybe even write custom SQL queries long hand with out a GUI.
Ok, I trimmed down the create script since the generated scripts are extremely verbose, and use database specific commands.

Other than maybe having to edit the data types or something (on Sql Server datetime would become date if I remember correctly) this should be pretty close to working on most databases.

It definitely works on MySql - just tested it. All the verbose stuff guarantees that when you run the script again on another MySql database server, it will use the same table type, and database name as it was originally. In this case it's easier for you to let the system defaults work their magic.

CREATE TABLE company (
CompanyId INT(11) NOT NULL AUTO_INCREMENT ,
CompanyName VARCHAR(45) NOT NULL ,
Street VARCHAR(45) NOT NULL ,
City VARCHAR(45) NOT NULL ,
State VARCHAR(2) NOT NULL ,
Zip INT(5) NOT NULL ,
PRIMARY KEY (CompanyId)
);

CREATE TABLE contacts (
ContactId INT(11) NOT NULL AUTO_INCREMENT ,
Position VARCHAR(45) NOT NULL ,
FirstName VARCHAR(45) NOT NULL ,
LastName VARCHAR(45) NOT NULL ,
OfficePhone VARCHAR(45) NULL DEFAULT NULL ,
CellPhone VARCHAR(45) NULL DEFAULT NULL ,
Email VARCHAR(45) NULL DEFAULT NULL ,
PRIMARY KEY (ContactId)
);

CREATE TABLE company_contacts (
CompanyId INT(11) NOT NULL ,
ContactId INT(11) NOT NULL ,
PRIMARY KEY (CompanyId, ContactId) ,
INDEX fk_Company_has_Contacts_Contacts1_idx (ContactId ASC) ,
INDEX fk_Company_has_Contacts_Company_idx (CompanyId ASC) ,
CONSTRAINT fk_Company_has_Contacts_Company
FOREIGN KEY (CompanyId)
REFERENCES company (CompanyId)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT fk_Company_has_Contacts_Contacts1
FOREIGN KEY (ContactId)
REFERENCES contacts (ContactId)
ON DELETE NO ACTION
ON UPDATE NO ACTION
);

CREATE TABLE floorplans (
FloorplanId INT(11) NOT NULL AUTO_INCREMENT ,
CompanyId INT(11) NOT NULL ,
UnitName VARCHAR(45) NULL DEFAULT NULL ,
SquareFeet INT(11) NOT NULL ,
Bedrooms INT(11) NOT NULL ,
ListPrice DECIMAL(7,2) NOT NULL ,
Description TEXT NOT NULL ,
PRIMARY KEY (FloorplanId) ,
INDEX fk_Floorplans_Company1_idx (CompanyId ASC) ,
CONSTRAINT fk_Floorplans_Company1
FOREIGN KEY (CompanyId)
REFERENCES company (CompanyId)
ON DELETE NO ACTION
ON UPDATE NO ACTION
);

CREATE TABLE installers (
InstallerId INT(11) NOT NULL AUTO_INCREMENT ,
InstallerName VARCHAR(45) NOT NULL ,
PRIMARY KEY (InstallerId)
);

CREATE TABLE salesorders (
SalesOrderId INT(11) NOT NULL AUTO_INCREMENT ,
FloorplanId INT(11) NOT NULL ,
InstallAddress VARCHAR(200) NOT NULL ,
SalePrice DECIMAL(7,2) NOT NULL ,
InstallerId INT(11) NULL DEFAULT NULL ,
OrderDate DATETIME NOT NULL ,
InstallDateReq DATETIME NOT NULL ,
InstallComplete DATETIME NULL DEFAULT NULL ,
Paid TINYINT(1) NOT NULL DEFAULT '0' ,
PRIMARY KEY (SalesOrderId) ,
INDEX fk_SalesOrders_Floorplans1_idx (FloorplanId ASC) ,
INDEX fk_SalesOrders_Installers1_idx (InstallerId ASC) ,
CONSTRAINT fk_SalesOrders_Floorplans1
FOREIGN KEY (FloorplanId)
REFERENCES floorplans (FloorplanId)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT fk_SalesOrders_Installers1
FOREIGN KEY (InstallerId)
REFERENCES installers (InstallerId)
ON DELETE NO ACTION
ON UPDATE NO ACTION
);
See less See more
You will need to create a database for this to run against, then set the interpreter to run commands on that database. You do that like this:

create database MyCompany;
use MyCompany;
Updated EER diagram

EDIT again ...: Writing the insert queries I noticed that I didn't change some things that I normally do differently from the way the MySql code generator does.

Now I remember why I don't use identifying relationships ...

Ill see if I can update the image to reflect so I don't have to add another one ...

Text Line Software Font Computer program
See less See more
Here's the inserts to insert data for each table.

Note: there are fields that require data from other tables to be there, or you'll get errors when you try to insert them.

insert into contacts (
Position,
FirstName,
LastName,
OfficePhone,
CellPhone,
Email
)
values (
'Apartment Manager',
'Jane',
'Smith',
'555 555 5555',
'555 111 1111',
'[email protected]'
);

insert into company (
CompanyName,
Street,
City,
State,
Zip
)
values (
'Slum Villas',
'5025 Ghetto Lane',
'Detroit',
'MI',
'54666'
);

insert into company_contacts (CompanyId,ContactId) values (1,1);

insert into floorplans (
CompanyId,
UnitName,
SquareFeet,
Bedrooms,
ListPrice,
Description
)
values (
1,
'The Junkworth',
350,
1,
325.00,
'walls, promar 200 flat color code 0-23-1248. Trim painted with wall paint, same color. Ceilings: ceiling white. Countertop refinish color: almond.'
);

insert into floorplans (
CompanyId,
UnitName,
SquareFeet,
Bedrooms,
ListPrice,
Description
)
values (
1,
'The Methanado',
550,
2,
525.00,
'walls, promar 200 flat color code 5693458. Trim painted with chemical resistant epoxy in almond. Ceilings: ceiling white. Countertop refinish color: bright white.'
);

insert into installers (InstallerName) values ('DriftWeed');

insert into salesorders (
FloorplanId,
InstallAddress,
SalePrice,
InstallerId,
OrderDate,
InstallDateReq
)
values (
1,
'3250 White Horse Drive, Detroit, MI 35402',
325.00,
1,
now(),
now()
);
See less See more
One thing you wanted to do is to pull a list of jobs that a particular installer worked on.

If you wanted to find out every job that Driftweed has ever done you could do something like this:

select * from salesorders where InstallerId = 1

the * means "all fields". It's not good form at all when you're building the front end, but for now it'll do.

This will produce 1 record since we only have 1 sales order.

When I inserted the record, I used "now()" for the datetime fields to make it easy on me so I could focus on the big picture. The installdatereq field is when they want the job done - like next tuesday. "now()" as you can imagine is just the current time on the computers internal clock.

One more thing - the "InstallComplete" field has no value, and is allowed to be null. When the installer finishes the job, you enter a date.

So right now, the above query lists all jobs the installer has ever done, AND jobs currently assigned.

To filter out jobs that are currently assigned, and ONLY get jobs that are complete you use the "where" clause of the select query.

select * from salesorders where InstallerId = 1 and InstallComplete is not null

At this point it won't return any rows since there are no sales records that match that criteria.
See less See more
21 - 40 of 105 Posts
This is an older thread, you may not receive a response, and could be reviving an old thread. Please consider creating a new thread.
Top