I had a frustrating day trying to code a spreadsheet project that required numerous mathematical formulas. It felt like taking two steps forward and one step back, especially with the project’s complexity.
On a positive note, my therapy session was helpful. I discussed with my therapist how my mind tends to replay thoughts repeatedly and obsessively, which leads me to feel scared and alone. My therapist suggested that I should talk to someone I feel close to instead of bottling up my feelings. I was assigned “homework” to express my feelings more and open up my thoughts to others. I tend to internalize everything and stay trapped in my bubble, so it’s hard to find words to express my feelings, even when someone asks me directly. I hope to improve in this aspect and gain the courage to share my thoughts.
Today has been busy with a therapy session in the middle of the day. I felt that I needed to rush through everything I did today to get it done. However, I did manage to finish the spreadsheet project and get the laundry done. Although, the clothes are still in the dryer and need to be put away. Additionally, I must fill my pillbox to make my mornings smoother. Going into each individual pill bottle is a time-consuming task that I’d rather avoid.
JavaScript notes…
—————————–
Spreadsheet steps 91 – 103
Step 91
Now your update() function can actually evaluate formulas. Remember that you wrote the if condition to check that a function was called.
Inside your if statement, set the value of the element to be the result of your evalFormula() function. Do not pass any arguments yet.
const update = event => { const element = event.target; const value = element.value.replace(/\s/g, ""); if (!value.includes(element.id) && value.startsWith('=')) { element.value = evalFormula(); } }
Step 92
The first argument for your evalFormula call needs to be the contents of the cell (which you stored in value). However, the contents start with an = character to trigger the function, so you need to pass the substring of value starting at index 1.
const update = event => { const element = event.target; const value = element.value.replace(/\s/g, ""); if (!value.includes(element.id) && value.startsWith('=')) { element.value = evalFormula(value.slice(1)); } }
Step 93
You can quickly get all cells from your page by getting the #container element by it’s id and accessing the children property of the result. Pass that to your evalFormula() call as the second parameter.
const update = event => { const element = event.target; const value = element.value.replace(/\s/g, ""); if (!value.includes(element.id) && value.startsWith('=')) { element.value = evalFormula(value.slice(1), document.getElementById('container').children); } }
Step 94
Unfortunately, that children property is returning a collection of elements, which is array-like but not an array. Wrap your second argument in Array.from() to convert it to an array.
const update = event => { const element = event.target; const value = element.value.replace(/\s/g, ""); if (!value.includes(element.id) && value.startsWith('=')) { element.value = evalFormula(value.slice(1), Array.from(document.getElementById("container").children)); } }
Step 95
Your spreadsheet is now functional. However, you don’t have support for very many formulas.
Add an even property to your spreadsheetFunctions. It should take a nums parameter, and return the result of filtering the nums array to only include even numbers. Use a reference to your isEven function to help.
const spreadsheetFunctions = { sum, average, median, even: nums => nums.filter(isEven), }
Step 96
Add a firsttwo property which takes a nums parameter and returns the first two elements of the nums array. Then add a lasttwo property which returns the last two elements of the nums array.
const spreadsheetFunctions = { sum, average, median, even: nums => nums.filter(isEven), firsttwo: nums => nums.slice(0, 2), lasttwo: nums => nums.slice(-2), }
Step 97
Add a has2 property which returns whether the nums array has 2 in the values, and an increment property which returns nums with every value incremented by one.
const spreadsheetFunctions = { sum, average, median, even: nums => nums.filter(isEven), firsttwo: nums => nums.slice(0, 2), lasttwo: nums => nums.slice(-2), has2: nums => nums.includes(2), increment: nums => nums.map(num => num + 1) }
Step 98
Arrays have a .some() method. Like the .filter() method, .some() accepts a callback function which should take an element of the array as the argument. The .some() method will return true if the callback function returns true for at least one element in the array.
Here is an example of a .some() method call to check if any element in the array is an uppercase letter.
const arr = [“A”, “b”, “C”];
arr.some(letter => letter === letter.toUpperCase());
Add a someeven property to your spreadsheetFunctions – use the .some() method to check if any element in the array is even.
const spreadsheetFunctions = { sum, average, median, even: nums => nums.filter(isEven), someeven: nums => nums.some(isEven), firsttwo: nums => nums.slice(0, 2), lasttwo: nums => nums.slice(-2), has2: nums => nums.includes(2), increment: nums => nums.map(num => num + 1), }
Step 99
Arrays have an .every() method. Like the .some() method, .every() accepts a callback function which should take an element of the array as the argument. The .every() method will return true if the callback function returns true for all elements in the array.
Here is an example of a .every() method call to check if all elements in the array are uppercase letters.
const arr = [“A”, “b”, “C”];
arr.every(letter => letter === letter.toUpperCase());
Add an everyeven property to your spreadsheetFunctions – use the .every() method to check if any element in the array is even.
const spreadsheetFunctions = { sum, average, median, even: nums => nums.filter(isEven), someeven: nums => nums.some(isEven), everyeven: nums => nums.every(isEven), firsttwo: nums => nums.slice(0, 2), lasttwo: nums => nums.slice(-2), has2: nums => nums.includes(2), increment: nums => nums.map(num => num + 1), }
Step 100
Create a random property. This property should use the first two numbers from an array to generate a random whole number. The range for this number starts at the smaller positive number (inclusive) among the first two numbers and ends just before the sum of these two numbers. Use the Math.floor() and Math.random() methods for the calculation.
const spreadsheetFunctions = { sum, average, median, even: nums => nums.filter(isEven), someeven: nums => nums.some(isEven), everyeven: nums => nums.every(isEven), firsttwo: nums => nums.slice(0, 2), lasttwo: nums => nums.slice(-2), has2: nums => nums.includes(2), increment: nums => nums.map(num => num + 1), random: ([x, y]) => Math.floor(Math.random() * y + x), }
Step 101
Add a range property which generates a range from nums. Remember that you have a range function you can reuse here.
const spreadsheetFunctions = { sum, average, median, even: nums => nums.filter(isEven), someeven: nums => nums.some(isEven), everyeven: nums => nums.every(isEven), firsttwo: nums => nums.slice(0, 2), lasttwo: nums => nums.slice(-2), has2: nums => nums.includes(2), increment: nums => nums.map(num => num + 1), random: ([x, y]) => Math.floor(Math.random() * y + x), range: nums => range(...nums), }
Step 102
The last function has a few approaches to implement, and you are free to choose whichever approach you would like.
Add a nodupes property which returns nums with all duplicate values removed. For example, [2, 1, 2, 5, 3, 2, 7] should return [2, 1, 5, 3, 7].
const spreadsheetFunctions = { sum, average, median, even: nums => nums.filter(isEven), someeven: nums => nums.some(isEven), everyeven: nums => nums.every(isEven), firsttwo: nums => nums.slice(0, 2), lasttwo: nums => nums.slice(-2), has2: nums => nums.includes(2), increment: nums => nums.map(num => num + 1), random: ([x, y]) => Math.floor(Math.random() * y + x), range: nums => range(...nums), nodupes: nums => [...new Set(nums)], }
Step 103
Finally, to handle potential edge cases, add an empty string property (you will need to use quotes) which is a function that takes a single argument and returns that argument.
With that, your spreadsheet project is now complete. You are welcome to experiment with adding support for even more functions.
const spreadsheetFunctions = { '': arg => arg, sum, average, median, even: nums => nums.filter(isEven), someeven: nums => nums.some(isEven), everyeven: nums => nums.every(isEven), firsttwo: nums => nums.slice(0, 2), lasttwo: nums => nums.slice(-2), has2: nums => nums.includes(2), increment: nums => nums.map(num => num + 1), random: ([x, y]) => Math.floor(Math.random() * y + x), range: nums => range(...nums), nodupes: nums => [...new Set(nums).values()] }