-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfifo.html
444 lines (382 loc) · 50.2 KB
/
fifo.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Improved FIFO COGS Tracking in Microsoft Excel</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- SEO Description -->
<meta name="author" content="Nicholas S. Selby">
<meta name="description" content="An open-source tool to track COGS using FIFO with multiple SKUs and consumables">
<link rel="canonical" href="https://rupumped.github.io/fifo.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Improved FIFO COGS Tracking in Microsoft Excel",
"image": [
"https://rupumped.github.io/blog/fifo.jpg",
"https://rupumped.github.io/blog-posts/fifo-cover.jpg"
],
"datePublished": "2024-10-18T00:00:00+00:00",
"author": [{
"@type": "Person",
"name": "Nicholas S. Selby",
"url": "https://rupumped.github.io/"
}]
}
</script>
<!-- Open Graph Tags -->
<meta property="og:title" content="Improved FIFO COGS Tracking in Microsoft Excel">
<meta property="og:description" content="An open-source tool to track COGS using FIFO with multiple SKUs and consumables">
<meta property="og:image" content="https://rupumped.github.io/blog/fifo.jpg">
<meta property="og:image:width" content="900">
<meta property="og:image:height" content="900">
<meta property="og:image:alt" content="An Excel table tracking FIFO COGS for various pie sales">
<meta property="og:url" content="https://rupumped.github.io/fifo.html">
<meta property="og:type" content="article">
<!-- Favicon -->
<link rel="icon" href="./favicon.ico" type="image/x-icon">
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&family=Raleway:wght@300;400;700&display=swap" rel="stylesheet">
<!-- Custom CSS -->
<link rel="stylesheet" type="text/css" href="main.css">
<link rel="stylesheet" type="text/css" href="secondary.css">
<link rel="stylesheet" type="text/css" href="blog-posts/blog-post.css">
<!-- KaTeX for Math -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous" onload="renderMathInElement(document.body);"></script>
<script src="https://rupumped.github.io/NicksAPPS/JavaScript/katex-support.js"></script>
</head>
<body>
<header>
<div class="header-content">
<a href="index.html" id="name">NICHOLAS S SELBY</a>
<nav>
<input class="menu-btn" type="checkbox" id="menu-btn">
<label class="menu-icon" for="menu-btn" tabindex="0"><span class="navicon"></span></label>
<ul class="menu">
<li><a href="index.html">HOME</a></li>
<li><a href="about.html">ABOUT</a></li>
<li><a href="selected-work.html">PROJECTS</a></li>
<li><a href="blog.html">BLOG</a></li>
<li><a href="service.html">SERVICE</a></li>
</ul>
</nav>
</div>
</header>
<main>
<h1>Improved FIFO COGS Tracking in Microsoft Excel</h1>
<p class="date">Posted on October 18, 2024 • 20-minute read</p>
<figure class="cover">
<img src="blog-posts/fifo-cover.jpg" alt="Two Excel tables showing orders placed for and sales of various pies">
</figure>
<section class="toc">
<h2>Contents</h2>
<div>
<ul>
<li><a href="#Intro">Introduction</a></li>
<li><a href="#Goal">Goal</a></li>
<li><a href="#PriorArt">Prior Art</a></li>
<li><a href="#Formalization">Formalizing the FIFO Problem</a></li>
<li><a href="#Algorithm">An Improved Algorithm</a></li>
<li><a href="#Implementation">Implementation in Excel</a></li>
<li><a href="#Consumables">Extension to Consumables</a></li>
<li><a href="#Conclusion">Conclusion</a></li>
</ul>
</div>
</section>
<section id="Intro">
<h2>Introduction</h2>
<p>This post is an answer to the question asked by <a rel="external" target="_blank" href="https://learnesy.com/fifo-calculation-in-excel/">Emil</a>, <a rel="external" target="_blank" href="https://pakaccountants.com/fifo-costing-inventory-excel-data-tables/">Hasaan Fazal</a>, <a rel="external" target="_blank" href="https://www.eloquens.com/tool/3BgVCy0x/finance/inventory-management-excel-templates/fifo-based-cogs-inventory-valuation-template-in-excel">Jason Varner</a>, and others: can Excel track the cost of goods sold (COGS) using the first-in-first-out (FIFO) inventory valuation standard? I will explain why previous solutions are unsatisfactory and provide what I believe to be a better alternative.</p>
<p>Alternatively, for those in a hurry, here is <a href="blog-posts/improved-fifo-cogs-tracking.xlsx" download target="_blank">a quick example to download</a>. It looks like the header image at the top of this post.</p>
</section>
<section id="Goal">
<h2>Goal</h2>
<p>Given a table of orders and a table of sales, create a calculated column, COGS, for the sales table. Ideally, the method should be software agnostic (i.e. have analogs in Google Sheets and LibreOffice Calc), extend easily to the tracking of consumables, and allow for the tracking of different SKUs in the same table.</p>
<p>As an example, consider a pie distributor that sells three different flavors (SKUs) of pie: pecan, rhubarb, and apple. Here, "orders" refers to the purchases made by the distributor of its pie suppliers to restock the distributor's inventory, and "sales" refers to the sales made by the distributor to its customers depleting the distributor's inventory. The distributor's Orders table should have columns for the order date, flavor of pie, quantity purchased, and cost per unit. The Sales table should have columns for sale date, flavor of pie sold, and quantity sold. The distributor desires to add a calculated column to the Sales table containing the COGS for each sale.</p>
</section>
<section id="PriorArt">
<h2>Prior Art</h2>
<p><a rel="external" target="_blank" href="https://learnesy.com/fifo-calculation-in-excel/">Emil</a> provides a quick solution to this problem by tracking the quantity of purchased assets sold and the associated COGS in the Orders table rather than the Sales table. Emil provides a quick solution to this problem by tracking the quantity of purchased assets sold and the associated COGS in the Orders table rather than the Sales table. For each entry in the Orders table, the method calculates the difference between the total number of sold assets from the Sales table and the sum of all previously sold quantities from the Orders table. The quantity of the current order that was sold is then determined by taking the minimum of this calculated remainder and the quantity of the current order. Finally, the COGS is computed by multiplying this sold quantity by the current price per unit.</p>
<figure>
<img class="img-center" src="blog-posts/fifo-emil.jpg" alt="Screenshot of two Excel tables: purchased assets and sold assets">
<figcaption>Credit: Emil. "FIFO Calculation in Excel." <i>Learnesy</i>.</figcaption>
</figure>
<p>While Emil's solution is elegantly simple, it has a significant limitation: it tracks COGS in the Orders table rather than the Sales table. This approach, though efficient, may not meet standard FIFO inventory tracking requirements. Most accounting practices and regulatory standards mandate that the cost of goods <b>sold</b> be recorded in the Sales table, not the Orders table.</p>
<p><a rel="external" target="_blank" href="https://pakaccountants.com/fifo-costing-inventory-excel-data-tables/">Hasaan's approach</a> builds upon Emil's solution, adapting it to track COGS in the Sales table using Excel's Data Tables feature. First, the sum of sales is extracted from the Sales table as a static input cell, rather than a calculated value. Next, Emil's solution is applied to each row of the Orders table, calculating the COGS. These individual COGS values are then summed to produce a total COGS for the entire sale. Then, Excel's Data Tables functionality is leveraged to run this method for each row in a newly created Sales table, effectively transferring the COGS tracking to the sales side.</p>
<p>While Hasaan's solution stands out as my favorite among those I found online, it has some limitations. Namely, it lacks the capability to track consumables or handle multiple SKUs simultaneously. Also, the method relies heavily on Excel's Data Tables, a feature for which Google Sheets currently lacks a direct equivalent.</p>
<figure>
<img class="img-center" src="blog-posts/fifo-xkcd.jpg" alt="XKCD comic with a character saying "Seems unnecessary. When I need to do arbitrary computation, I just add a giant block of columns to the side of my sheet and have a Turing machine traverse down it."" style="width: 7cm;">
<figcaption><a rel="external" target="_blank" href="https://www.xkcd.com/2453/">CC BY-NC 2.5 Randall Munroe</a></figcaption>
</figure>
<p><a rel="external" target="_blank" href="https://www.eloquens.com/tool/3BgVCy0x/finance/inventory-management-excel-templates/fifo-based-cogs-inventory-valuation-template-in-excel">Jason</a> applies similar logic as Hasaan, but replaces Hasaan's Data Tables with massive helper matrices to calculate Emil's intermediate quantities sold from each order. This solution still lacks the ability to track consumables and multiple SKUs simultaneously, but it is easily portable between softwares and results in a Sales table with a COGS column out of the box. Unfortunately, it is not perfectly autonomous; the helper matrices must be manually resized to ensure they always have both more rows and columns than the number of rows in the Orders and Sales tables.</p>
</section>
<section id="Formalization">
<h2>Formalizing the FIFO Problem</h2>
<p>The fundamental challenge in FIFO COGS calculation lies in the complexity of tracking inventory depletion over time.</p>
<ol>
<li>Let \(\mathrm{S}=\{\mathrm{s}_1, \mathrm{s}_2, \ldots, \mathrm{s}_N\}\) be a finite sequence of \(N\) previous supply entries, where each \(\mathrm{s}_i\) is a pair \((\mathrm{q}_i, \mathrm{c}_i)\) such that \(\mathrm{q}_i\geq 0\) is the quantity of goods in the \(i\)-th supply entry, and \(\mathrm{c}_i\geq 0\) is the cost per unit of goods in the \(i\)-th supply entry.</li>
<li>Given a total quantity already sold \(\mathrm{Q}'\geq 0\) and a target additional quantity \(\mathrm{Q}\geq 0\), calculate the total cost \(\mathrm{C}\) of fulfilling this quantity using the FIFO (First-In-First-Out) method from the infinite sequence \(\mathrm{S}\).</li>
<li>Define \(\mathrm{COGS}(\mathrm{Q}, \mathrm{Q}', \mathrm{S}) = \mathrm{C}\), where:
<div class="equation">
\begin{equation}
\mathrm{C} = \sum_{i=1}^n \left( \min \left(\mathrm{Q}+\mathrm{Q}'-\sum_{j=1}^{i-1} \mathrm{q}_j, \mathrm{q}_i - \mathrm{min} \left(\mathrm{q}_i, \mathrm{Q}'-\sum_{j=1}^{i-1} \mathrm{q}_j \right) \right) \times \mathrm{c}_i \right)
\end{equation}
</div>
where \(n\) is the smallest natural number such that \(\sum_{i=1}^n \mathrm{q}_i \geq \mathrm{Q}+\mathrm{Q}'\).
</li>
</ol>
<p>The calculation requires finding the prefix of \(\mathrm{S}\) (i.e. an initial portion of \(\mathrm{S}\)) that satisfies the condition \(\sum_{i=1}^n \mathrm{q}_i \geq \mathrm{Q}+\mathrm{Q}'\). The sum in the COGS calculation stops at \(n\), but \(n\) itself is not known in advance and could be arbitrarily large, so long as \(n \leq N\).</p>
<p>Put simply, according to FIFO, the COGS for a given target quantity is the sum of all the COGS for the contributions of the individual supply orders. For any given supply order \(i\), the quantity sold from that order is the minimum of the quantity supplied in that order remaining in inventory and the quantity left to sell after having sold all the previous orders. The quantity supplied in order \(i\) remaining in inventory is the difference between the original quantity in that order \(\mathrm{q}_i\) and the amount already sold from the order, the minimum of \(\mathrm{Q}'\) and the cumulative supply before order \(i\). The quantity left to sell after having sold all the previous orders is the difference between the target quantity and the quantity already sold, the difference between the cumulative supply before order \(i\) and \(\mathrm{Q}'\). Finally, the contribution of order \(i\) to the COGS is the quantity sold from that order times the cost per unit of that order, \(\mathrm{c}_i\).</p>
</section>
<section id="Algorithm">
<h2>An Improved Algorithm</h2>
<p>Given a sequence of supply entries \(\mathrm{S}\), a total quantity already sold \(\mathrm{Q}'\), and a target additional quantity \(\mathrm{Q}\):</p>
<ol>
<li>Define the cumulative supply function:
<div class="equation">
\begin{equation}
\mathrm{CS}(i) \coloneqq \sum_{j=1}^{i} \mathrm{q}_j
\end{equation}
</div>
</li>
<li>Define index functions that identify key positions in the sequence:
<div class="equation">
\begin{equation}
\begin{cases}
\mathrm{first}(\mathrm{Q}',\mathrm{S}) \coloneqq \min_{\mathrm{CS}(i)\gt \mathrm{Q}'} i \\
\mathrm{last}(\mathrm{Q},\mathrm{Q}',\mathrm{S}) \coloneqq 1+\max_{\mathrm{CS}(i)\lt \mathrm{Q}+\mathrm{Q}'} i \\
\end{cases}
\end{equation}
</div>
</li>
<li>COGS can be decomposed into three components, the cost of oldest goods sold, the cost of the middle goods sold, and the cost of the newest goods sold:
<div class="equation">
\begin{equation}
\mathrm{COGS}(\mathrm{Q},\mathrm{Q}',\mathrm{S}) = \mathrm{COOGS}(\mathrm{Q},\mathrm{Q}',\mathrm{S}) + \mathrm{COMGS}(\mathrm{Q},\mathrm{Q}',\mathrm{S}) + \mathrm{CONGS}(\mathrm{Q},\mathrm{Q}',\mathrm{S})
\end{equation}
</div>
where
<div class="equation">
\begin{equation}
\mathrm{COOGS}(\mathrm{Q},\mathrm{Q}',\mathrm{S}) \coloneqq \min \left( \mathrm{CS}(\mathrm{first}(\mathrm{Q}',\mathrm{S})) -\mathrm{Q}', \mathrm{Q} \right) \times \mathrm{c}_{\mathrm{first}(\mathrm{Q}',\mathrm{S})}
\end{equation}
</div>
and
<div class="equation">
\begin{equation}
\mathrm{COMGS}(\mathrm{Q},\mathrm{Q}',\mathrm{S}) \coloneqq \sum_{i=\mathrm{first}(\mathrm{Q}',\mathrm{S})+1}^{\mathrm{last}(\mathrm{Q},\mathrm{Q}',\mathrm{S})-1} \mathrm{q}_i \times \mathrm{c}_i
\end{equation}
</div>
and
<div class="equation">
\begin{equation}
\mathrm{CONGS}(\mathrm{Q},\mathrm{Q}',\mathrm{S}) \coloneqq \left( \mathrm{Q} - \min \left( \mathrm{CS}(\mathrm{first}(\mathrm{Q}',\mathrm{S})) -\mathrm{Q}', \mathrm{Q} \right) - \sum_{i=\mathrm{first}(\mathrm{Q}',\mathrm{S})+1}^{\mathrm{last}(\mathrm{Q},\mathrm{Q}',\mathrm{S})-1} \mathrm{q}_i \right)\times \mathrm{c}_{\mathrm{last}(\mathrm{Q},\mathrm{Q}',\mathrm{S})}
\end{equation}
</div>
</li>
</ol>
<p>Put simply, the first order at least partially consumed by this sale is the first order for which the cumulative supply is greater than the total quantity already consumed. The last order at least partially consumed by this sale is the order immediately after the last order for which the cumulative supply is less than the sum of the total quantity already consumed and the new target quantity. The cost of oldest goods sold is the product of the quantity consumed from that first order and the per-unit cost of that order. The quantity consumed from that first order is the minimum of the quantity remaining in that first order and the target quantity, where the quantity remaining in that first order is the difference between the cumulative supply up through the first order and the quantity already consumed. The cost of middle goods sold is the sum of the products of the quantities in the middle orders and the respective per-unit costs. The cost of newest goods sold is the product of the quantity consumed from the last order and the per-unit cost of that order, where the quantity consumed from that last order is difference between the target quantity and the sum of the quantites sold from the oldest and middle orders.</p>
</section>
<section id="Implementation">
<h2>Implementation in Excel</h2>
<p>The solution presented here will come in three parts: calculating the cost of the oldest goods (still in inventory) sold (COOGS), calculating the cost of the newest goods sold (CONGS), and calculating the cost of the remaining, middle goods sold (COMGS). COGS will therefore be the sum of COOGS, COMGS, and CONGS.</p>
<p>Begin with the two tables illustrated below. The first table, Orders, has columns "Date," "Flavor," "Qty Purchased," and "Cost Per Unit" in columns A through D of the spreadsheet. The second table, Sales, has columns "Date," "Flavor," "Qty Sold," and "COGS" in columns G through J of the spreadsheet. Row 1 is reserved for the table names. Row 2 is reserved for the column headers. The data begins in row 3. With the exception of the COGS column, both tables are entirely filled with data representing the details of various orders and sales. Note that the tables need not be the same size, dates can be repeated, and both tables should be sorted by date.</p>
<img class="img-center" src="blog-posts/fifo-pie-start.jpg" alt="Screenshot of two Excel tables: Orders and Sales">
<ol>
<li>Add columns to track the cumulative quantities of goods ordered and sold to the Orders and Sales tables, respectively. Add a column "Cumulative Ordered" to the Orders table in column E of the Excel workbook. Enter the formula <code>=SUMIF(B$3:B3, [@Flavor], C$3:C3)</code> into cell E3, then copy that cell into the remaining rows in that column. Likewise, add a column "Cumulative Sold" to the Sales table in column K of the Excel workbook. Enter the formula <code>=SUMIF(H$3:H3, [@Flavor], I$3:I3)</code> into cell K3, then copy that cell into the remaining rows.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>This works because SUMIF is an Excel function that sums values based on a condition. <code>B$3:B3</code> and <code>H$3:H3</code> are the ranges for the condition (Flavor column of the Orders and Sales tables, respectively), with the top row anchored. <code>[@Flavor]</code> is the criterion (the Flavor of the current row). <code>C$3:C3</code> and <code>I$3:I3</code> are the ranges to sum (Qty Purchased and Sold columns), with the top row anchored. This formula calculates the running total of quantities purchased and sold, respectively, for each flavor up to the current row.</p>
</details>
</li>
<li>Add a column "Index of Last Sale" to the Sales table in column L. Enter the formula <code>=IFERROR(XMATCH([@Flavor], H$2:H2, 0, -1)-1, 0)</code> into cell L3, copying it into the remaining rows.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>The XMATCH function is used to find the position of a match in an array. <code>[@Flavor]</code> is the lookup value, which is the flavor of the current row. <code>H$2:H2</code> is the lookup array, the Flavor column in the Sales table up to the current row. <code>0</code> is the match mode, specifying an exact match. <code>-1</code> is the search mode, indicating to search from last to first (or bottom to top). The result of XMATCH is subtracted by 1 (<code>XMATCH(...) - 1</code>) to account for the header row. The IFERROR function is used to handle cases where XMATCH does not find a match. If XMATCH fails (e.g., if this is the first sale of a particular flavor), IFERROR will return 0.</p>
<p>The purpose of this formula is to find the index of the last sale of the same flavor before the current row. It searches the Flavor column from the current row upwards for a match to the current flavor. If a match is found, it returns the index of that row. If no match is found (meaning this is the first sale of this flavor), it returns 0.</p>
<p>This "Index of Last Sale" helps determine the state of inventory before the current sale. It is used in subsequent formulas to calculate quantities and costs based on the previous sales of the same flavor.</p>
</details>
</li>
<li>Add a column "Total Qty Sold Before This Sale" to the Sales table in column M. Enter the formula <code>=[@[Cumulative Sold]] - [@[Qty Sold]]</code> into cell M3, copying it into the remaining rows.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>By subtracting the current sale quantity from the cumulative sold quantity, I get the total quantity sold before this particular sale. The purpose of this calculation is to determine how much of a particular flavor had been sold prior to the current sale.</p>
</details>
</li>
<li>Add a column "Index of Oldest Order Still in Inventory Before This Sale" to the Sales table in column N. Enter the formula <code>=XMATCH([@[Total Qty Sold Before This Sale]], FILTER(Orders[Cumulative Ordered], (Orders[Flavor] = [@Flavor]) * (Orders[Date] < [@Date])), 1, 1)</code> into cell N3, copying it into the remaining rows.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>The FILTER function filters the "Cumulative Ordered" column from the Orders table. It applies two conditions. First, <code>Orders[Flavor] = [@Flavor]</code> only includes rows where the flavor matches the current sale's flavor. Second, <code>Orders[Date] < [@Date]</code> only includes orders with dates earlier than the current sale date. The result is an array of cumulative ordered quantities for the same flavor, from orders placed before the current sale.</p>
<p>The XMATCH function looks for <code>[@[Total Qty Sold Before This Sale]]</code>, the total quantity sold before this sale, in the filtered array of cumulative ordered quantities. Using a match mode of <code>1</code> finds the smallest value that is greater than or equal to the lookup value, and a search mode of <code>1</code> returns the first match in the lookup array.</p>
<p>This formula first filters the Orders table to only consider relevant orders (same flavor, earlier dates). Then, it searches this filtered list of cumulative ordered quantities to find the first entry that is greater than or equal to the total quantity sold before this sale. The result is the index of the oldest order that still has inventory available for this sale. This index helps identify which historical order's inventory and cost should be used for this sale.</p>
</details>
</li>
<li>Add a column "Qty of Oldest Order Left in Inventory Before This Sale" to the Sales table in column O. Enter the formula <code>=INDEX(FILTER( Orders[Cumulative Ordered], (Orders[Flavor] = [@Flavor]) * (Orders[Date] < [@Date])), [@[Index of Oldest Order Still in Inventory Before This Sale]]) - IF([@[Index of Last Sale]]=0, 0, INDEX(K2:K$3, [@[Index of Last Sale]]))</code> into cell O3, copying it into the remaining rows.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>This formula consists of two main parts connected by a subtraction operation:</p>
<ol>
<li>
<p><code>INDEX(FILTER( Orders[Cumulative Ordered], (Orders[Flavor] = [@Flavor]) * (Orders[Date] < [@Date])), [@[Index of Oldest Order Still in Inventory Before This Sale]])</code></p>
<p>The FILTER function filters the "Cumulative Ordered" column from the Orders table, including only rows where the flavor matches the current sale's flavor and the order date is earlier than the current sale date. The INDEX function retrieves the value from the filtered array at the position specified by "Index of Oldest Order Still in Inventory Before This Sale." This part gives us the cumulative quantity ordered up to the oldest order that still has inventory available for this sale.</p>
</li>
<li>
<p><code>IF([@[Index of Last Sale]]=0, 0, INDEX(K2:K$3, [@[Index of Last Sale]]))</code></p>
<p>The IF function checks if there was a previous sale of this flavor. If "Index of Last Sale" is 0 (meaning this is the first sale of this flavor), it returns 0. Otherwise, it uses INDEX to retrieve the cumulative sold quantity from the previous sale (column K). By subtracting the second part from the first part, I get the quantity of the oldest order that is still left in inventory before this sale.</p>
</li>
</ol>
</details>
</li>
<li>Add a column "Cost Per Unit of Oldest Inventory" to the Sales table in column P. Enter the formula <code>=INDEX(FILTER(Orders[Cost Per Unit], Orders[Flavor] = [@Flavor]), [@[Index of Oldest Order Still in Inventory Before This Sale]])</code> into cell P3, copying it into the remaining rows.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>The FILTER function filters the "Cost Per Unit" column from the Orders table. It only includes rows where the flavor in the Orders table matches the flavor of the current sale. The INDEX function retrieves a value from the filtered array of costs using the "Index of Oldest Order Still in Inventory Before This Sale" as the row number to determine which cost to retrieve. Thus, it picks the cost per unit that corresponds to the oldest order that still has inventory available for this sale.</p>
</details>
</li>
<li>Add a column titled "Qty of Oldest Order Sold" to the Sales table in column Q. Enter the formula <code>=MIN([@[Qty of Oldest Order Left in Inventory Before This Sale]], [@[Qty Sold]])</code> into cell Q3, copying it into the remaining rows.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>If the quantity of the oldest order left in inventory is larger than or equal to the quantity sold in this transaction, the formula will return the quantity sold. This means the entire sale can be fulfilled from the oldest inventory. If, instead, the quantity of the oldest order left in inventory is smaller than the quantity sold in this transaction, the formula will return the quantity of the oldest order left. This means only a portion of the sale can be fulfilled from the oldest inventory, and the rest will need to come from newer inventory.</p>
</details>
</li>
<li>Add a column titled "COOGS" to the Sales table in column R. Enter the formula <code>=[@[Qty of Oldest Order Sold]] * [@[Cost Per Unit of Oldest Inventory]]</code> into cell R3, copying it into the remaining rows.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>This multiplies the quantity of the oldest inventory being sold in this transaction by the cost per unit of that oldest inventory, resulting in the total cost of the oldest goods sold in this transaction.</p>
</details>
</li>
<li>Add a column titled "Additional Qty Needed" to the Sales table in column S. Enter the formula <code>=[@[Qty Sold]] - [@[Qty of Oldest Order Sold]]</code> into cell S3, copying it into the remaining cells.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>This subtracts the quantity of the oldest inventory being sold in this transaction from the total quantity sold in this transaction, resulting in the quantity of inventory being sold in this transaction coming from newer orders.</p>
</details>
</li>
<li>Add a column titled "Index of Last Order Consumed" to the Sales table in column T. Enter the formula <code>=XMATCH([@[Cumulative Sold]], FILTER(Orders[Cumulative Ordered], (Orders[Flavor] = [@Flavor]) * (Orders[Date] < [@Date])), 1, 1)</code> into cell T3, copying it into the remaining cells.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>The XMATCH function looks up the total quantity sold up this sale ([@[Cumulative Sold]]) in an array of cumulative ordered quantities filtered to only include relevant orders. The FILTER function creates this array by applying two conditions: <code>Orders[Flavor] = [@Flavor]</code> only includes orders of the same flavor, and <code>Orders[Date] < [@Date]</code> only includes orders placed before the current sale date. Using a match mode of <code>1</code> means XMATCH will find the smallest value that is greater than or equal to the cumulative sold quantity, and a search mode of <code>1</code> returns the first match found. This effectively finds the index of the most recent order needed to fulfill this sale; in other words, the last order that must be consumed to have enough inventory for all sales up to this point.</p>
</details>
</li>
<li>Add a column titled "Index of Penultimate Order Consumed" to the Sales table in column U. Enter the formula <code>=IF([@[Index of Last Order Consumed]] = [@[Index of Oldest Order Still in Inventory Before This Sale]], [@[Index of Oldest Order Still in Inventory Before This Sale]], [@[Index of Last Order Consumed]]-1)</code> into cell U3, copying it into the remaining cells.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>This formula determines which order was consumed just before the final order needed for this sale. It uses an IF statement to handle two possible scenarios. First, it checks if <code>[@[Index of Last Order Consumed]]</code> equals <code>[@[Index of Oldest Order Still in Inventory Before This Sale]]</code>. If these are equal, it means only one order was needed to fulfill this sale, so the penultimate (second-to-last) order is the same as the oldest order still in inventory. In this case, it returns <code>[@[Index of Oldest Order Still in Inventory Before This Sale]]</code>. If they are not equal, meaning multiple orders were needed to fulfill this sale, it returns <code>[@[Index of Last Order Consumed]]-1</code>, which gives us the index of the order just before the last one consumed. This helps track which orders were used to fulfill the sale when inventory needs to be drawn from multiple orders.</p>
</details>
</li>
<li>Add a column titled "Qty Sold from Middle Orders" to the Sales table in column V. Enter the formula <code>=IF([@[Index of Penultimate Order Consumed]] = [@[Index of Oldest Order Still in Inventory Before This Sale]], 0, SUM( INDEX(FILTER(Orders[Qty Purchased], (Orders[Flavor] = [@Flavor]) * (Orders[Date] < [@Date])), SEQUENCE(1, [@[Index of Penultimate Order Consumed]] - [@[Index of Oldest Order Still in Inventory Before This Sale]], [@[Index of Oldest Order Still in Inventory Before This Sale]]+1, 1))))</code> into cell V3, copying it into the remaining cells.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>This formula calculates how much inventory was sold from the "middle" orders, those that fall between the oldest order still in inventory and the last order consumed. It consists of two main parts connected by an IF statement. First, it checks if <code>[@[Index of Penultimate Order Consumed]]</code> equals <code>[@[Index of Oldest Order Still in Inventory Before This Sale]]</code>. If they are equal, it means there are no "middle" orders; the sale only used inventory from one or two orders, so it returns 0. If they are not equal, it calculates the sum of quantities from the middle orders using several nested functions:</p>
<ul>
<li><code>FILTER(Orders[Qty Purchased], (Orders[Flavor] = [@Flavor]) * (Orders[Date] < [@Date]))</code> creates an array of quantities purchased, filtered to only include the same flavor and orders before the current sale date.</li>
<li><code>SEQUENCE(1, [@[Index of Penultimate Order Consumed]] - [@[Index of Oldest Order Still in Inventory Before This Sale]], [@[Index of Oldest Order Still in Inventory Before This Sale]]+1, 1)</code> generates a sequence of indices for the middle orders, starting from the order after the oldest and continuing until the penultimate order.</li>
<li>INDEX selects the quantities from the filtered array using these sequence numbers.</li>
<li>SUM adds up all these quantities to get the total amount sold from middle orders.</li>
</ul>
<p>This calculation helps track how much inventory was sold from orders that were completely consumed during this sale.</p>
</details>
</li>
<li>Add a column titled "Qty Sold from Newest Order" to the Sales table in column W. Enter the formula <code>=[@[Additional Qty Needed]] - [@[Qty Sold from Middle Orders]]</code> into cell W3, copying it into the remaining cells.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>This formula calculates how much inventory was sold from the newest (most recent) order needed for this sale. <code>[@[Additional Qty Needed]]</code> represents the total quantity that could not be fulfilled from the oldest order, while <code>[@[Qty Sold from Middle Orders]]</code> represents how much was fulfilled from completely consumed middle orders. By subtracting these values, we get the quantity that must have come from the newest order used in this sale.</p>
</details>
</li>
<li>Add a column titled "COMGS" to the Sales table in column X. Enter the formula <code>=IF([@[Qty Sold from Middle Orders]]=0, 0, LET(oIUITS, SEQUENCE(1, [@[Index of Penultimate Order Consumed]] - [@[Index of Oldest Order Still in Inventory Before This Sale]], [@[Index of Oldest Order Still in Inventory Before This Sale]]+1, 1), SUMPRODUCT( INDEX(FILTER(Orders[Qty Purchased],(Orders[Flavor] = [@Flavor]) * (Orders[Date] < [@Date])), oIUITS), INDEX(FILTER(Orders[Cost Per Unit], (Orders[Flavor] = [@Flavor]) * (Orders[Date] < [@Date])), oIUITS))))</code> into cell X3, copying it into the remaining cells.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>This formula calculates the Cost of Middle Goods Sold (COMGS), the cost of inventory sold from orders that were completely consumed. It uses a LET function to improve readability and efficiency. First, it checks if <code>[@[Qty Sold from Middle Orders]]</code> is 0. If true, there were no middle orders consumed, so it returns 0. If there were middle orders, it uses LET to create a named calculation:</p>
<ul>
<li><code>oIUITS</code>, "order indeces used in this sale," is defined using SEQUENCE to generate an array of indices for the middle orders, starting after the oldest order and continuing through the penultimate order consumed.</li>
<li>FILTER is used twice to create arrays of quantities purchased and costs per unit, filtered to only include the same flavor and orders before the current sale date.</li>
<li>INDEX selects the relevant quantities and costs using the sequence of indices.</li>
<li>SUMPRODUCT multiplies each quantity by its corresponding cost and adds up all the results.</li>
</ul>
<p>The end result is the total cost of all inventory sold from orders that were completely consumed during this sale. This represents the middle portion of our FIFO cost calculation, between the oldest and newest inventory used.</p>
</details>
</li>
<li>Add a column titled "CONGS" to the Sales table in column Y. Enter the formula <code>=[@[Qty Sold from Newest Order]] * INDEX(FILTER(Orders[Cost Per Unit], (Orders[Flavor] = [@Flavor]) * (Orders[Date] < [@Date])), [@[Index of Last Order Consumed]])</code> into cell Y3, copying it into the remaining cells.
<details>
<summary><span class="reveal-answer-button"><span class="reveal">Explain This Step</span><span class="hide">Hide Explanation</span></span></summary>
<p>This formula calculates the Cost of Newest Goods Sold (CONGS), the cost of inventory sold from the most recent order needed for this sale. <code>[@[Qty Sold from Newest Order]]</code> represents how much inventory was taken from the newest order used in this sale. This is multiplied by the cost per unit from that order, which is found using INDEX to select the cost from the filtered array costs using [@[Index of Last Order Consumed]] to identify the correct row. This multiplication gives us the total cost of the portion of inventory that came from the newest order used in this sale, completing our FIFO cost calculation along with COOGS (oldest inventory) and COMGS (middle orders).</p>
</details>
</li>
<li>Finally, return to the COGS column (J) in the Sales table and enter the formula <code>=[@COOGS] + [@COMGS] + [@CONGS]</code> into each cell. If you want, you can safely hide all the helper columns, E and K through Y.</li>
</ol>
<img class="img-center" style="width: 23cm;" src="blog-posts/fifo-pie-finish.jpg" alt="Screenshot of two Excel tables: Orders and Sales. The Sales table has a COGS column with correctly calculated values.">
</section>
<section id="Consumables">
<h2>Extension to Consumables</h2>
<p>Some SKUs, like diesel in the tank of a backup generator for a solar mini-grid, do not have points of discrete outflow, and therefore cannot be tracked simply in a "Sales" table. Instead, inventory is tracked in a single table with columns for date, SKU, starting balance, qty purchased, and price per unit. The rows, sorted by date, serve a dual purpose: measuring current supply—and therefore consumption since the previous row—of an SKU, and recording new inventory if an order has been made.</p>
<img class="img-center" style="width: 20cm;" src="blog-posts/fifo-diesel.jpg" alt="An Excel table tracking diesel purchases and measurements for several sites projects">
<p>Consider an example diesel tracker for a company's three mini-grids. The table has the above mentioned columns: Date, Project, Starting Balance, Liters Purchased, and Price Per Liter, where Project is the SKU, Starting Balance is the amount of diesel in the tank prior to the diesel purchase, and Liters Purchased and Price Per Liter may be left zero if no diesel was purchased on that date. Each row corresponds to a different log of the diesel balance and optional diesel purchase for a mini-grid. I can extend the above methodology for calculating COGS to compute a FIFO "Cost of Consumption" for diesel consumed between each log recorded in a row of the table.</p>
<ol>
<li>Add a column "Ending Balance" that is the sum of the Starting Balance and the Liters Purchased.</li>
<li>Use the method for calculating the "Index of Last Sale," above, to calculate an "Index of Last Entry."</li>
<li>Add a column "Diesel Used" using the formula <code>=IF([@[Index of Last Entry]]=0, 0, INDEX([Ending Balance], [@[Index of Last Entry]]) - [@[Starting Balance]])</code>. This formula checks to see if the entry is the first of its Project, in which case the diesel usage is assumed to be zero. Otherwise, it returns the difference between the Ending Balance of the previous row from this Project and the Starting Balance of the current row.</li>
</ol>
<p>The remaining columns can be calculated using the same methodology as the above COGS calculations, although you may want to adjust the column names for relevance, with the following changes to account for there being no Orders table:</p>
<ul>
<li>Instead of filtering ranges to precede the current row's date, you can adjust the array input of the FILTER function to include only rows above the current row using Excel's structured referencing. For example, if the Cumulative Supply column is in column K, the Project names are in column B, and row 1 is reserved for column headers, then the filtered Cumulative Supplies could be calculated using <code>FILTER(K$1:K9, B$1:B9=[@Project])</code> for row 9.</li>
<li>You must enclose the formulas for "Index of Oldest Diesel Still in Tank Before This Consumption," "Liters of Oldest Diesel Left in Tank Before This Consumption," and "Price Per Liter of Oldest Diesel"—analogous to "Index of Oldest Order Still in Inventory Before This Sale," "Qty of Oldest Order Left in Inventory Before This Sale," and "Cost Per Unit of Oldest Inventory," respectively—in IF statements that return 0 if the Index of Last Entry is 0.</li>
<li>You must enclose the formulas for "Price of Last Diesel Consumed," analogous to "CONGS," in an IF statement that returns 0 if the Liters Consumed from Last Order is 0.</li>
</ul>
<p>I have included a working example of a FIFO diesel tracker in <a href="blog-posts/improved-fifo-cogs-tracking.xlsx" download target="_blank">the example download</a>.</p>
</section>
<section id="Conclusion">
<h2>Conclusion</h2>
<p>If you are in charge of your company's inventory tracking and reporting standards, use AVCO instead of FIFO. It is simpler to calculate, hedges against inflation for a business's tax liability, and is allowed by both the <a rel="external" target="_blank" href="https://www.ifrs.org/content/dam/ifrs/publications/pdf-standards/english/2021/issued/part-a/ias-2-inventories.pdf">International Financial Reporting Standards</a> and the <a rel="external" target="_blank" href="https://asc.fasb.org/1943274/2147482954/330-10-30-9">Generally Accepted Accounting Principles</a>.</p>
<p>If you are not in charge, and your boss requires you use FIFO, I hope this tutorial saves you time.</p>
</section>
</main>
<footer>
<div id="top-footer">
<div id="footer-socials">
<a aria-label="My LinkedIn profile" rel="external" href="https://www.linkedin.com/in/nicholas-selby-5278b334/" target="_blank">
<svg viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg" aria-labelledby="LinkedIn-title LinkedIn-desc">
<title id="LinkedIn-title">LinkedIn</title>
<desc id="LinkedIn-desc">LinkedIn icon</desc>
<path d="m416 32h-384.1c-17.6 0-31.9 14.5-31.9 32.3v383.4c0 17.8 14.3 32.3 31.9 32.3h384.1c17.6 0 32-14.5 32-32.3v-383.4c0-17.8-14.4-32.3-32-32.3zm-280.6 384h-66.4v-213.8h66.5v213.8zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5s17.2-38.5 38.5-38.5c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4v-104c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9v105.8h-66.4v-213.8h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/>
</svg>
</a>
<a aria-label="My Google Scholar Profile" rel="external" href="https://scholar.google.com/citations?user=SKcs1pEAAAAJ" target="_blank">
<svg viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg" aria-labelledby="Google-Scholar-title Google-Scholar-desc">
<title id="Google-Scholar-title">Google Scholar</title>
<desc id="Google-Scholar-desc">Google Scholar icon</desc>
<path d="m48 32c-26.5 0-48 21.5-48 48v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-352c0-26.5-21.5-48-48-48zm140.69531 64h178.24024l-16.47071 12.85938v22.69335c6.1159.78532 5.46875 4.46019 5.46875 8.85743v107.22265c0 4.96563-4.06205 9.0293-9.02734 9.0293h-3.32422c-4.96563 0-9.0293-4.06403-9.0293-9.0293v-107.22265c0-4.40781-.63995-8.08659 5.52149-8.86133v-14.26563l-47.42383 38.89258c.54795 1.01573 1.06775 1.6675 1.5625 2.51953 4.16684 7.37735 6.28906 16.54919 6.28906 27.75977 0 8.59325-1.43204 16.31497-4.33593 23.13086-2.89082 6.81736-6.4066 12.38451-10.50782 16.67383-4.10119 4.30429-8.21545 8.23614-12.33008 11.77734-4.11326 3.54813-7.62906 7.24664-10.50781 11.08789-2.90139 3.82814-4.34765 7.78747-4.34765 11.88867 0 4.10814 1.87594 8.28085 5.61328 12.48633 3.72386 4.2186 8.30529 8.30635 13.72265 12.34375 5.42938 4.01043 10.84634 8.46278 16.26368 13.30664 5.42904 4.83584 9.98706 11.06107 13.71093 18.62109 3.75047 7.58518 5.625 15.93732 5.625 25.11719 0 12.10928-3.08756 23.04599-9.24609 32.7793-6.17204 9.69317-14.21877 17.42887-24.10156 23.09961-9.90904 5.70939-20.50722 10.00631-31.8086 12.91015-11.32797 2.87733-22.56501 4.32227-33.78906 4.32227-7.08423 0-14.23265-.5475-21.42187-1.66602-7.21219-1.12-14.43823-3.09828-21.7168-5.88476-7.29167-2.80655-13.75106-6.25079-19.34961-10.39063-5.61205-4.09467-10.12984-9.38173-13.59375-15.82031-3.46392-6.43852-5.18359-13.67857-5.18359-21.71875 0-9.53863 2.65694-18.38532 7.98242-26.63476 5.32512-8.18928 12.3823-15.02552 21.1582-20.44141 15.31325-9.52549 39.33645-15.4113 72.03125-17.63672-7.47326-9.34283-11.22266-18.13975-11.22266-26.36914 0-4.68271 1.22186-9.69984 3.64454-15.11719-3.90652.54687-7.9286.85352-12.03125.85352-17.56273 0-32.39541-5.70952-44.43946-17.20703-12.04402-11.47856-18.05859-25.8462-18.05859-43.2168 0-1.81599.05219-3.41866.18164-5.18945h-71.378907zm31.37891 38.33398c-11.19892 0-19.79186 4.02906-25.78125 12.07032-5.9879 8.02012-8.98438 17.73465-8.98438 29.14648 0 9.71981 1.64061 19.61644 4.92188 29.70703 3.2681 10.08548 8.62123 19.08948 16.12109 27.02539 7.47324 7.95594 16.17192 11.92578 26.05469 11.92578 11.01591 0 19.62286-3.68944 25.79492-11.07226 6.14505-7.37043 9.23047-16.67343 9.23047-27.87891 0-9.54517-1.6264-19.537-4.89453-29.98633-3.25608-10.46247-8.68505-19.90262-16.26367-28.30664-7.55234-8.4321-16.30333-12.63086-26.19922-12.63086zm18.51758 172.08008c-8.03469 0-15.93905.71228-23.69922 2.13086-7.76017 1.37996-15.41675 3.70986-22.96875 6.99805-7.57861 3.26958-13.69819 8.07499-18.35938 14.42969-4.68784 6.34667-7.01953 13.82169-7.01953 22.42187 0 8.19582 2.05913 15.50628 6.17383 21.87305 4.10265 6.32768 9.51795 11.28394 16.25 14.83203 6.73201 3.55471 13.78885 6.23613 21.1582 8 7.3828 1.75184 14.89682 2.66406 22.55274 2.66406 15.14262 0 28.17578-3.41115 39.11328-10.22851 10.91054-6.8159 16.38086-17.34206 16.38086-31.54883 0-2.98812-.41689-5.93201-1.23828-8.80274-.85861-2.90389-1.70365-5.3892-2.53711-7.45312-.83345-2.02525-2.42173-4.4673-4.76563-7.2793-2.33081-2.81861-4.11569-4.90255-5.31445-6.28906-1.2239-1.43208-3.51215-3.47703-6.88672-6.17969-3.34426-2.71375-5.48032-4.40548-6.43164-5.03125h-.00195c-.93771-.65762-3.3717-2.4355-7.29102-5.32031-3.9189-2.91084-6.06651-4.45407-6.44531-4.63672-2.05736-.37077-4.94607-.58008-8.66992-.58008z"/>
</svg>
</a>
<a aria-label="My GitHub profile" rel="external" href="https://github.com/rupumped" target="_blank">
<svg viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg" aria-labelledby="GitHub-title GitHub-desc">
<title id="GitHub-title">GitHub</title>
<desc id="GitHub-desc">GitHub icon</desc>
<path d="M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM277.3 415.7c-8.4 1.5-11.5-3.7-11.5-8 0-5.4.2-33 .2-55.3 0-15.6-5.2-25.5-11.3-30.7 37-4.1 76-9.2 76-73.1 0-18.2-6.5-27.3-17.1-39 1.7-4.3 7.4-22-1.7-45-13.9-4.3-45.7 17.9-45.7 17.9-13.2-3.7-27.5-5.6-41.6-5.6-14.1 0-28.4 1.9-41.6 5.6 0 0-31.8-22.2-45.7-17.9-9.1 22.9-3.5 40.6-1.7 45-10.6 11.7-15.6 20.8-15.6 39 0 63.6 37.3 69 74.3 73.1-4.8 4.3-9.1 11.7-10.6 22.3-9.5 4.3-33.8 11.7-48.3-13.9-9.1-15.8-25.5-17.1-25.5-17.1-16.2-.2-1.1 10.2-1.1 10.2 10.8 5 18.4 24.2 18.4 24.2 9.7 29.7 56.1 19.7 56.1 19.7 0 13.9.2 36.5.2 40.6 0 4.3-3 9.5-11.5 8-66-22.1-112.2-84.9-112.2-158.3 0-91.8 70.2-161.5 162-161.5S388 165.6 388 257.4c.1 73.4-44.7 136.3-110.7 158.3zm-98.1-61.1c-1.9.4-3.7-.4-3.9-1.7-.2-1.5 1.1-2.8 3-3.2 1.9-.2 3.7.6 3.9 1.9.3 1.3-1 2.6-3 3zm-9.5-.9c0 1.3-1.5 2.4-3.5 2.4-2.2.2-3.7-.9-3.7-2.4 0-1.3 1.5-2.4 3.5-2.4 1.9-.2 3.7.9 3.7 2.4zm-13.7-1.1c-.4 1.3-2.4 1.9-4.1 1.3-1.9-.4-3.2-1.9-2.8-3.2.4-1.3 2.4-1.9 4.1-1.5 2 .6 3.3 2.1 2.8 3.4zm-12.3-5.4c-.9 1.1-2.8.9-4.3-.6-1.5-1.3-1.9-3.2-.9-4.1.9-1.1 2.8-.9 4.3.6 1.3 1.3 1.8 3.3.9 4.1zm-9.1-9.1c-.9.6-2.6 0-3.7-1.5s-1.1-3.2 0-3.9c1.1-.9 2.8-.2 3.7 1.3 1.1 1.5 1.1 3.3 0 4.1zm-6.5-9.7c-.9.9-2.4.4-3.5-.6-1.1-1.3-1.3-2.8-.4-3.5.9-.9 2.4-.4 3.5.6 1.1 1.3 1.3 2.8.4 3.5zm-6.7-7.4c-.4.9-1.7 1.1-2.8.4-1.3-.6-1.9-1.7-1.5-2.6.4-.6 1.5-.9 2.8-.4 1.3.7 1.9 1.8 1.5 2.6z"/>
</svg>
</a>
<a aria-label="My RSS feed" href="rss.xml">
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-143 145 512 512" xml:space="preserve" aria-labelledby="RSS-title RSS-desc">
<title id="RSS-title">RSS</title>
<desc id="RSS-desc">RSS icon</desc>
<path d="M329,145h-432c-22.1,0-40,17.9-40,40v432c0,22.1,17.9,40,40,40h432c22.1,0,40-17.9,40-40V185C369,162.9,351.1,145,329,145z M43.1,518.7c-6.2,6.2-14.7,9.9-24.1,9.9c-9.4,0-17.8-3.8-24-9.9c-6.2-6.2-10-14.6-10-23.9c0-9.4,3.8-17.8,10-24s14.6-10,24-10 c9.4,0,17.9,3.8,24,10c6.2,6.2,10,14.6,10,24C53,504.2,49.2,512.6,43.1,518.7z M104.8,529c-0.1-32.1-12.5-62.3-35.1-84.9 c-22.6-22.6-52.8-35.2-84.7-35.2V360c46.6,0,88.7,19,119.3,49.6c30.6,30.6,49.5,72.8,49.6,119.4H104.8z M192,529 c-0.1-114.2-92.8-207.1-206.9-207.1V273c70.6,0,134.5,28.7,180.8,75.1c46.3,46.4,75,110.3,75.1,180.9H192z"/>
</svg>
</a>
</div>
<div id="footer-initials">
NSS
</div>
<div id="footer-nav">
<a href="mailto:[email protected]">CONTACT</a>
<a href="index.html">HOME</a>
<a href="sitemap.xml">SITEMAP</a>
</div>
</div>
<p id="copyright">
© 2018–2024 This work by <a href="https://rupumped.github.io" property="cc:attributionName" rel="cc:attributionURL">Nicholas S. Selby</a> is licensed under a <a rel="license" target="_blank" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>. Feel free to fork the <a rel="external" target="_blank" href="https://github.com/rupumped/rupumped.github.io">source code</a> from GitHub and create your own website using this template.
</p>
</footer>
</body>
</html>