
I wanted to come up with a way to organize the listed vehicles that are on my radar, and determine which ones are the best overall value, with the attributes most important to us. This "Value Score" should take into account multiple attributes and apply a weighted normalization or multi-crieteria decision analysis (MCDA) algorithm to each attributes weighted according to how important they are to us.
I created a Google Sheet of all the relevant dealership listings I found, so I could share with my wife. Google recent added Data Tables to Sheets, and you can have Dropdown's for nice tidy data validation in each column - I made use of this for almost every column, except for Price, Odo KM.
My Data looks like this (Table name = CarListings):
| Make/Model | Year | Trim | Trim Level | Dealer | Price | km | Color | Range | Length | Heat Pump | Remote Start | Location | Days Listed | Distance | Damage |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chevrolet Bolt EUV | 2023 | LT | 1 | Park Lane Cadillac | $22,995 | 62,000 | Grey | 397 km | 169" | β | Fob, App | Sarnia | 36 | 4 | 0 |
| Kia Niro EV | 2020 | SX Touring | 3 | Titanium Auto Sales | $23,990 | 75,000 | Gravity Blue | 385km | 171" | β | App | Springbank | 86 | 1 | 0 |
| Hyundai Kona Electric | 2021 | Preferred | 1 | Stricklands | $24,650 | 37,000 | White | 415km | 164" | β | Fob, App | Stratford | 63 | 2 | 0 |
| Chevrolet Bolt EV | 2022 | 1LT | 3 | MacMaster GM | $25,495 | 91,000 | White | 417km | 163" | β | Fob, App | Airport | 20 | 1 | 0 |
| Chevrolet Bolt EV | 2022 | 1LT | 3 | Audi London | $25,495 | 46,450 | Grey | 417km | 163" | β | Fob, App | Wharncliffe South | 6 | 1 | 0 |
| Nissan Leaf | 2023 | SL Plus | 3 | Stricklands Toyota | $26,888 | 8,743 | White | 342 km | 176" | β | App | Stratford | 9 | 2 | 0 |
| Hyundai Kona Electric | 2021 | Ultimate | 3 | Maple Auto | $26,990 | 55,000 | Grey | 415km | 164" | β | Fob, App | Wharncliffe South | 15 | 1 | 0 |
| Hyundai Kona Electric | 2024 | Preferred | 1 | Woodstock Chrysler | $29,995 | 29,643 | Grey | 420 km | 171" | β | Fob, App | Woodstock | 14 | 2 | 25000 |
| Hyundai Kona Electric | 2021 | Ultimate | 3 | London Airport Hyundai | $32,995 | 70,000 | Red | 415km | 164" | β | Fob, App | Airport | 383 | 1 | 0 |
| Kia Niro EV | 2024 | Wind+ | 2 | Milton Kia | $33,995 | 30,683 | Grey | 407km | 174" | β | Fob, App | Milton | 74 | 5 | 0 |
| Kia Niro EV | 2023 | Premium Plus | 2 | 401 Dixie Kia | $29,998 | 51,336 | Grey | 407km | 174" | β | Fob, App | Mississauga | 97 | 5 | 0 |
| Kia Niro EV | 2021 | EX | 1 | Brampton Autopark | $21,990 | 81,054 | Black | 385km | 171" | β | Fob, App | Brampton | 13 | 5 | 0 |
Trim Level is a hidden calculated columns with VLOOKUP from separate sheet Trim Lookup, to assign a numerical value based on the relative trim level - e.g. 2020 Kia Niro EV comes in 3 trim levels EX, EX+, and SX Touring; I assign 1 to EX, 2 to EX+, and 3 to SX Touring so I can weight the Trims =IFERROR(INDEX(FILTER(TrimLevel[Trim Level], (TrimLevel[Trim]=E2)*(TrimLevel[Make/Model]=C2)), 1), "No Match")Distance calculated columns with VLOOKUP from separate sheet Distance Lookup, to assign a numerical value based on the relative distance I'm willing to travel to buy a car. - e.g. 1 for same city, 2 for close by town, 3-5 for other cities within 2 hours. =IFERROR(VLOOKUP(CarListings[Location],DistanceLookup,2,FALSE),999)Days Listed, I have a calculated column that calculates the number of days between when the Listing was first posted to today, e.g. =TODAY()-DATE(2025,11,12) = 7 daysHere is my "Trim Lookup" table (in its own sheet), which is used to build the Make/Model and Trim data validation dropdowns on the main table, and calculate the Trim Level value. The Trim Level is a number between 1 to 3 (could be higher if there are more Trims for a particular model) to differentiate the more expensive, feature-rich trims (higher number) vs the more basic trims (lower number), and give us a common comparison across different makes and models.
| Make/Model | Trim | Trim Level |
|---|---|---|
| Chevrolet Bolt EUV | LT | 2 |
| Chevrolet Bolt EUV | Premier | 3 |
| Chevrolet Bolt EV | 1LT | 3 |
| Chevrolet Bolt EV | 1LT | 3 |
| Hyundai Kona Electric | Preferred | 2 |
| Hyundai Kona Electric | Ultimate | 3 |
| Hyundai Kona Electric | Essential | 1 |
| Kia Niro EV | SX Touring | 3 |
| Kia Niro EV | EX | 1 |
| Kia Niro EV | Premium+ | 2 |
| Kia Niro EV | Wind+ | 2 |
| Kia Niro EV | Wave | 3 |
| Kia Niro EV | Limited | 3 |
| Kia Niro EV | EX+ | 2 |
| Kia Niro EV | Premium | 1 |
| Nissan Leaf | SL Plus | 3 |
| Nissan Leaf | SL | 2 |
| Nissan Leaf | SV Plus | 1 |
| Kia Soul EV | Limited | 3 |
| Kia Soul EV | Premium | 2 |
Here is my "Distance Lookup" table (in its own sheet), which is used to build the Location data validation dropdown on the main table, and calculate the Distance value. A lower number is closer (e.g. 1 is in-town), whereas a higher number is farther.
| Location | Distance |
|---|---|
| Springbank | 1 |
| Airport | 1 |
| Wharncliffe South | 1 |
| Stratford | 2 |
| Woodstock | 2 |
| Sarnia | 3 |
| Paris | 3 |
| Guelph | 4 |
| Milton | 5 |
| Mississauga | 5 |
| Brampton | 5 |
Although you can sort your table by one or more columns, (Price ascending, then Odo ascending) I felt the order wasn't giving me a true representation of my most preferred vehicles in the list. I wanted to sort them in a more holistic way, to truly rank the listings on my preferences.
We need a sheet that has the weights we assign to each attribute, so we can easily and dynamically update them as needed. Create a new sheet called "Weights Lookup". Add a row for each column you want to consider in your Value Score. Here are my weights, and I converted the data into a Table named WeightsValue.
| Column | Weight |
|---|---|
| Price | 35% |
| Odo | 16% |
| Range | 12% |
| Year | 10% |
| Trim Level | 10% |
| Distance | 10% |
| Remote Start | 10% |
| Length | 10% |
| Damage | 5% |
| Heat Pump | 5% |
| Total | 123% |
Note: It is ok if the total is more than 100% (they aren't really a %, more of a relative amount).
Create a Insert a new column called Value Score (I put mine to the left of all others). The formula should look up attributes from each row and do some calculations as to its rank and apply our Weights from the WeightsValue table. It also has IFERROR to protect from Divide-By-Zero errors. The formula:
=ROUND(
(
IFERROR((CarListings[Year]-MIN(CarListings[Year]))
/(MAX(CarListings[Year])-MIN(CarListings[Year])),0)*IFERROR(VLOOKUP("Year",WeightsValue,2,FALSE),0) +
IFERROR((CarListings[Trim Level]-MIN(CarListings[Trim Level]))
/(MAX(CarListings[Trim Level])-MIN(CarListings[Trim Level])),0)*IFERROR(VLOOKUP("Trim Level",WeightsValue,2,FALSE),0) +
IFERROR((MAX(CarListings[Price])-CarListings[Price])
/(MAX(CarListings[Price])-MIN(CarListings[Price])),0)*IFERROR(VLOOKUP("Price",WeightsValue,2,FALSE),0) +
IFERROR((MAX(CarListings[Odo KM])-CarListings[Odo KM])
/(MAX(CarListings[Odo KM])-MIN(CarListings[Odo KM])),0)*IFERROR(VLOOKUP("Odo",WeightsValue,2,FALSE),0) +
IFERROR((CarListings[Range (km)]-MIN(CarListings[Range (km)]))
/(MAX(CarListings[Range (km)])-MIN(CarListings[Range (km)])),0)*IFERROR(VLOOKUP("Range",WeightsValue,2,FALSE),0) +
IFERROR((MAX(CarListings[Distance])-CarListings[Distance])
/(MAX(CarListings[Distance])-MIN(CarListings[Distance])),0)*IFERROR(VLOOKUP("Distance",WeightsValue,2,FALSE),0) +
IFERROR((MAX(CarListings[Damage])-CarListings[Damage])
/(MAX(CarListings[Damage])-MIN(CarListings[Damage])),0)*IFERROR(VLOOKUP("Damage",WeightsValue,2,FALSE),0) +
IF(CarListings[Heat Pump]="β",1,0)*IFERROR(VLOOKUP("Heat Pump",WeightsValue,2,FALSE),0) +
IF(CarListings[Remote Start]="Fob, App",1,0)*IFERROR(VLOOKUP("Remote Start",WeightsValue,2,FALSE),0) +
IFERROR((MAX(CarListings[Length (Inches)])-CarListings[Length (Inches)])
/(MAX(CarListings[Length (Inches)])-MIN(CarListings[Length (Inches)])),0)*IFERROR(VLOOKUP("Length",WeightsValue,2,FALSE),0)
)
/ IFERROR(SUM(WeightsValue[Weight]),1) * 127 / 100
,4)
Here is an explanation of my attributes and how they are used in the formula:
(MAX(CarListings[Price])-CarListings[Price])/(MAX(CarListings[Price])-MIN(CarListings[Price]))*VLOOKUP("Price",WeightsValue,2,FALSE)
(MAX(CarListings[Odo KM])-CarListings[Odo KM])/(MAX(CarListings[Odo KM])-MIN(CarListings[Odo KM]))*VLOOKUP("Odo",WeightsValue,2,FALSE)
(CarListings[Range (km)]-MIN(CarListings[Range (km)]))/(MAX(CarListings[Range (km)])-MIN(CarListings[Range (km)]))*VLOOKUP("Range",WeightsValue,2,FALSE)
Range column, it is text not numeric; so I created a hidden Range (km) helper calculated column that takes just the numeric value from the Range column =IF(ROW()=1,"Range_Numeric",VALUE(REGEXEXTRACT(CarListings[Range],"[0-9]+")))(CarListings[Year]-MIN(CarListings[Year]))/(MAX(CarListings[Year])-MIN(CarListings[Year]))*VLOOKUP("Year",WeightsValue,2,FALSE)
(CarListings[Trim Level]-MIN(CarListings[Trim Level]))/(MAX(CarListings[Trim Level])-MIN(CarListings[Trim Level]))*VLOOKUP("Trim Level",WeightsValue,2,FALSE)(MAX(CarListings[Distance])-CarListings[Distance])/(MAX(CarListings[Distance])-MIN(CarListings[Distance]))*VLOOKUP("Distance",WeightsValue,2,FALSE)
Distance column (with lookup from Distance Lookup table), and takes the difference between the Distance for a listing and the MAX Distance in the column, divided by the range in Distance, multiplied by our Distance Weighting (0.1)IF(CarListings[Heat Pump]="β",1,0)*VLOOKUP("Heat Pump",WeightsValue,2,FALSE)
β boolean symbols into numeric 1 or 0, so we can multiply them by our Heat Pump Weighting (0.05).(MAX(CarListings[Length (Inches)])-CarListings[Length (Inches)])/(MAX(CarListings[Length (Inches)])-MIN(CarListings[Length (Inches)])),0)*VLOOKUP("Length",WeightsValue,2,FALSE)

Although this Value Score helps me to have a great way to sort my Google Sheet Car Listings in the preferred way, it isn't perfect. I don't take into account maintenance costs, warranty information, dealership reputation. Additionally, my weighting is subjective, based on my personal preferences (which is not necessarily bad, since this is for my personal benefit).
1 There are a few reasons that The Leaf is not my preferred EV. In my opinion: