<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ spreadsheets - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ spreadsheets - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 27 Jun 2026 16:35:23 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/spreadsheets/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Master Spreadsheets by Building 33 Projects ]]>
                </title>
                <description>
                    <![CDATA[ Spreadsheets are an essential tool for managing data, solving problems, and automating workflows, whether you're a student, professional, or hobbyist. Mastering them can unlock countless possibilities in productivity and creativity. Imagine automatin... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/master-spreadsheets-by-building-33-projects/</link>
                <guid isPermaLink="false">677ee4b10bc6d529ee0098b7</guid>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 07 Jan 2025 05:00:00 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1736369313578/8365821c-999a-4489-8971-dbf733954a26.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Spreadsheets are an essential tool for managing data, solving problems, and automating workflows, whether you're a student, professional, or hobbyist. Mastering them can unlock countless possibilities in productivity and creativity. Imagine automating emails, creating dynamic calendars, or generating invoices—all with just Excel or Google Sheets. This course offers a practical and hands-on way to take your spreadsheet skills to the next level.</p>
<p>We just published a <strong>Spreadsheet Projects</strong> course on the <a target="_blank" href="http://freeCodeCamp.org">freeCodeCamp.org</a> YouTube channel, developed by Eamonn Cottrell. In this course, you’ll build <strong>33 exciting projects</strong>, covering a wide range of spreadsheet techniques and tools. Most of these projects can be done with either Microsoft Excel or Google Sheets, making the course versatile and accessible to anyone looking to enhance their skills.</p>
<h3 id="heading-what-youll-build-and-learn">What You’ll Build and Learn:</h3>
<ul>
<li><p><strong>Personal Finance Tracker</strong>: Manage your budget with a personalized finance tracker.</p>
</li>
<li><p><strong>Dynamic Calendars</strong>: Create all-day event calendars, dynamic monthly calendars, and even daily task managers.</p>
</li>
<li><p><strong>Automation</strong>: Learn to send automated reminder emails and notifications, automate processes with Apps Script, and integrate spreadsheets with Google Calendar.</p>
</li>
<li><p><strong>Custom Features</strong>: Build user-defined functions, dynamic search bars, and lightbox-style image displays directly within your spreadsheets.</p>
</li>
<li><p><strong>Advanced Formulas and Scripts</strong>: Explore regular expressions, dependent drop-down lists, and custom VBA scripts to create advanced functionality.</p>
</li>
<li><p><strong>Business Tools</strong>: Develop tools like a bulk importer for QuickBooks, a dynamic invoice generator, and a mail merge system.</p>
</li>
<li><p><strong>Integration with Other Platforms</strong>: Extract data from LinkedIn, embed YouTube videos in sheets, and link Google Tables to Google Docs.</p>
</li>
<li><p><strong>Spreadsheet Design Tips</strong>: Learn formatting tricks, Excel shortcuts, and techniques to make your spreadsheets not only functional but also visually appealing.</p>
</li>
</ul>
<h3 id="heading-why-this-course-is-valuable">Why This Course is Valuable</h3>
<p>This course emphasizes real-world applications, giving you the ability to create tools that solve everyday problems and streamline workflows. Each project is carefully crafted to teach a new skill or concept, with clear explanations and practical examples. By the end, you’ll have a portfolio of projects that demonstrate your proficiency in spreadsheets and inspire you to build even more.</p>
<h3 id="heading-key-skills-youll-gain">Key Skills You’ll Gain:</h3>
<ul>
<li><p>Data organization and visualization</p>
</li>
<li><p>Automation and scripting with VBA and Apps Script</p>
</li>
<li><p>Advanced formula usage and dynamic interactivity</p>
</li>
<li><p>Integration with external platforms like YouTube, LinkedIn, and Google Calendar</p>
</li>
<li><p>Time-saving spreadsheet shortcuts and techniques</p>
</li>
</ul>
<p>With 33 projects covering a wide range of topics, this course offers a fun and engaging way to take your spreadsheet expertise to the next level. Whether you’re looking to improve productivity, manage data better, or impress your colleagues, these skills are invaluable.</p>
<p>Watch the full course on <a target="_blank" href="https://youtu.be/BBk3DXgodmI">the freeCodeCamp.org YouTube channel</a> (4-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/BBk3DXgodmI" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Microsoft Excel: 14 Time-Saving Keyboard Shortcuts ]]>
                </title>
                <description>
                    <![CDATA[ Microsoft Excel is the quintessential spreadsheet software used everywhere from universities to small businesses to enterprises. It’s a lifesaver for countless financial professionals, data analysts, and teachers. But it’s also one of those programs ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/microsoft-excel-keyboard-shortcuts/</link>
                <guid isPermaLink="false">670ead175b03d2b334e6560f</guid>
                
                    <category>
                        <![CDATA[ excel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Tue, 15 Oct 2024 17:57:43 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1728930420116/82fe0d9f-89fe-4332-82dc-43b44d4ee2dc.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Microsoft Excel is the quintessential spreadsheet software used everywhere from universities to small businesses to enterprises.</p>
<p>It’s a lifesaver for countless financial professionals, data analysts, and teachers. But it’s also one of those programs that virtually everyone in any role can benefit from learning.</p>
<p>A handful of shortcuts can go a long way in increasing your productivity (and enjoyment) while using Excel.</p>
<p>In this article, I’ll detail some of the many shortcuts that I have found helpful throughout my studies and career.</p>
<h3 id="heading-excel-shortcuts-well-cover">Excel Shortcuts We’ll Cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-execute-shortcuts-in-excel">How to Execute Shortcuts in Excel</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-create-a-table">Shortcut to Create a Table</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-create-a-pivot-table">Shortcut to Create a Pivot Table</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-autofit-column-sizes">Shortcut to AutoFit Column Sizes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-open-format-cells">Shortcut to Open Format Cells</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-center-contents-of-cell">Shortcut to Center Contents of Cell</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-fill-color">Shortcut to Fill Color</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-fill-contents-down-or-right">Shortcut to Fill Contents Down (or Right)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-show-or-hide-gridlines">Shortcut to Show or Hide Gridlines</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-show-all-formulas">Shortcut to Show all Formulas</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcuts-for-navigation-in-excel">Shortcuts for Navigation in Excel</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-open-the-autofilter-menu-in-excel">Shortcut to Open the AutoFilter Menu in Excel</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-create-a-slicer-in-excel">Shortcut to Create a Slicer in Excel</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-create-checkboxes-in-excel">Shortcut to Create Checkboxes in Excel</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-shortcut-to-create-charts-in-excel">Shortcut to Create Charts in Excel</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-other-notes">Other Notes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-more-shortcuts">More Shortcuts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-got-sheet">Got Sheet</a></p>
</li>
</ul>
<p>Here’s a video walkthrough of everything we’ll cover in this article:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/RfFhh0n4bMM" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-how-to-execute-shortcuts-in-excel">How to Execute Shortcuts in Excel</h2>
<p>In Excel, the more you can learn to do without touching your mouse, the better. Often, by keeping your hands on your keyboard, you can save a lot of time in each project.</p>
<p>As such, virtually every command imaginable is available as a keyboard shortcut.</p>
<p>The basic ones like <code>CTRL + S</code> for save and <code>CTRL + C</code> for copy are present. But Excel goes a step further…</p>
<p>The real power comes from the <code>alt</code> shortcuts. By pressing sequences of keys that typically start with <code>alt</code>, almost all of the actions in the Ribbon become available.</p>
<p>By simply pressing the <code>alt</code> key, all of the shortcut sequences available from the current view become highlighted in yellow on the ribbon:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728924144231/6b083a86-6db6-41e3-b960-4a06a5d3284f.png" alt="alt shortcuts in Excel" class="image--center mx-auto" width="1059" height="280" loading="lazy"></p>
<p>Incidentally, some of the shortcuts’ sequences are separated by commas, while at other times two letters appear next to each other. Their execution is the same. Simply press them in sequence.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728925276816/8867e861-ecd7-43d9-989d-dab2fef62d8a.png" alt="one vs two letter shortcut sequences" class="image--center mx-auto" width="169" height="89" loading="lazy"></p>
<p>Below, you’ll find some of my favorites, but keep in mind that you can easily view all the available shortcuts at any time by pressing <code>alt</code> and then continuing to press the appropriate keys for the corresponding tabs and actions.</p>
<h2 id="heading-shortcut-to-create-a-table">Shortcut to Create a Table</h2>
<h3 id="heading-keyboard-shortcut-ctrl-t">Keyboard Shortcut: <code>ctrl + t</code></h3>
<p>Tables in Excel are often the preferred format to begin manipulating and visualizing data. As long as the active cell is inside your data range, pressing <code>ctrl + t</code> will pop up a dialog and automatically select the data range to be used for the table.</p>
<p>It is adjustable if Excel gets a column or row wrong, and you can also toggle table headers on or off from this initial box.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728924526482/aa5ffdee-2327-4232-8a6d-c74e271f4bce.png" alt="create table in Excel" class="image--center mx-auto" width="342" height="204" loading="lazy"></p>
<h2 id="heading-shortcut-to-create-a-pivot-table">Shortcut to Create a Pivot Table</h2>
<h3 id="heading-keyboard-shortcut-alt-n-v-t">Keyboard shortcut: <code>alt + n, v, t</code></h3>
<p>Want to appear a lot smarter than you are? Learn the basics of pivot tables in ten minutes. Your coworkers will remain impressed for weeks.</p>
<p>To create a pivot table, simply click somewhere in your data range and press <code>ALT + n, v, t</code>.</p>
<p>Excel is smart enough to recognize the data range you likely want included even if it isn’t already formatted as a table.</p>
<p>A dialog box will pop up for you to confirm the data range and location for the pivot table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728924350920/21f22ae2-238c-4e73-9690-cbc538c46458.png" alt="21f22ae2-238c-4e73-9690-cbc538c46458" class="image--center mx-auto" width="635" height="357" loading="lazy"></p>
<h2 id="heading-shortcut-to-autofit-column-sizes">Shortcut to AutoFit Column Sizes</h2>
<h3 id="heading-keyboard-shortcut-alt-h-o-i">Keyboard Shortcut: <code>alt + h, o, i</code></h3>
<p>Ever get tired of resizing your columns so that the text in the cells doesn’t clip or spill? You can always double click the column boundary headings. This resizes the column to fit the widest cell’s contents.</p>
<p>The keyboard shortcut is much more efficient and allows you to autofit multiple columns in one fell swoop. Simply click and drag the column boundaries to select any number of columns. Execute the <code>alt + h, o, i</code> shortcut and all the columns in your active range will autofit their width.</p>
<p>You can also autofit cells individually by selecting one or more active cells and performing the same shortcut.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728924664667/9611fe54-9d2f-442c-9246-a3ab85b1e81d.png" alt="autofit column width in Excel" class="image--center mx-auto" width="411" height="427" loading="lazy"></p>
<h2 id="heading-shortcut-to-open-format-cells">Shortcut to Open Format Cells</h2>
<h3 id="heading-keyboard-shortcut-ctrl-1-or-alt-h-fm">Keyboard Shortcut: <code>CTRL + 1</code> or <code>alt + h, fm</code></h3>
<p>Unless you are content with mediocrity, you’ll be formatting the cells in your spreadsheet at some point to create more readable, user-friendly content.</p>
<p>The simplest shortcut to open up the Format Cells window is <code>CTRL + 1</code>, although if you want to flex your dexterity, <code>alt + h, fm</code> will get you there as well.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728925061866/0d773119-097f-479e-bcc5-5bb8ba311a5d.png" alt="Cell formatting options" class="image--center mx-auto" width="783" height="774" loading="lazy"></p>
<h2 id="heading-shortcut-to-center-contents-of-cell">Shortcut to Center Contents of Cell</h2>
<h3 id="heading-keyboard-shortcut-horizontal-alt-h-a-c">Keyboard Shortcut: (horizontal) <code>alt + h, a, c</code>,</h3>
<p>(vertical) <code>alt + h, a, m</code></p>
<p>We have it easy compared to web developers. There seems a never-ending supply of articles and videos reminding developers how to center <code>divs</code>.</p>
<p>In Excel, we need only remember two quick shortcuts.</p>
<ul>
<li><p>For horizontal centering: <code>alt + h, a, c</code></p>
</li>
<li><p>For vertical centering: <code>alt + h, a, m</code></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728925842812/56676126-976e-4f1d-bb8a-2bf7072f9342.png" alt="centering text in a cell in Excel" class="image--center mx-auto" width="453" height="372" loading="lazy"></p>
<p>There are other shortcuts for left, right, top and bottom alignment, but most of the time when we change the original alignment, it’s to center it.</p>
<h2 id="heading-shortcut-to-fill-color">Shortcut to Fill Color</h2>
<h3 id="heading-keyboard-shortcut-alt-h-h">Keyboard Shortcut: <code>alt + h, h</code></h3>
<p>For a quick highlight, it takes precious seconds to mouse up to the fill color icon. Pressing <code>alt + h, h</code> quickly toggles the color selection open.</p>
<p>Once it’s open, you can leave your mouse to the side and arrow down to your favorite color</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728926023010/6cebdbc6-e27e-4784-8cc8-d46dbf8c4985.png" alt="fill color menu in Excel" class="image--center mx-auto" width="385" height="603" loading="lazy"></p>
<h2 id="heading-shortcut-to-fill-contents-down-or-right">Shortcut to Fill Contents Down (or Right)</h2>
<h3 id="heading-keyboard-shortcut-down-ctrl-d-right-ctrl-r">Keyboard Shortcut: (down) <code>CTRL + D</code>, (right) <code>CTRL + R</code></h3>
<p>One of the most powerful features of Excel is the ability to drag formulas and functions down or across many cells, effectively reproducing a single calculation many times on different pieces of data.</p>
<p>By typing a formula in cell A8 in the image below, we can then highlight A8 and drag down to our heart’s content. Then, by pressing <code>CTRL + D</code>, the formula will be copied down into every highlighted cell.</p>
<p>By default, it will also preserve the relative reference of the cell. In other words, the next cell will contain the formula <code>A7 + A8</code> and then <code>A8 + A9</code>, and so on.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728927617121/35dd07d3-90ac-4c31-9318-1e588bff007c.png" alt="Dragging down" class="image--center mx-auto" width="1116" height="1349" loading="lazy"></p>
<h2 id="heading-shortcut-to-show-or-hide-gridlines">Shortcut to Show or Hide Gridlines</h2>
<h3 id="heading-keyboard-shortcut-alt-w-vg">Keyboard Shortcut: <code>alt + w, vg</code></h3>
<p>The mark of a real data analyst is not the quality of their reports, but the precision of their workbook. Gridlines have got to go. If you need lines, you can add borders.</p>
<p>Toggle off the gridlines with <code>alt + w, vg</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728926496034/ab39e08c-1ac2-4d4d-986e-1c79597a322e.png" alt="Shortcut to toggle off gridlines" class="image--center mx-auto" width="332" height="158" loading="lazy"></p>
<p>And if you need those borders immediately, highlight your data range and press <code>alt + h, b</code> to open up the border menu. If you simply need all borders, <code>alt + h, b, a</code> will do the trick</p>
<h2 id="heading-shortcut-to-show-all-formulas">Shortcut to Show all Formulas</h2>
<h3 id="heading-keyboard-shortcut-ctrl">Keyboard Shortcut: <code>CTRL + ~</code></h3>
<p>You’ll likely never lose control of a workbook.</p>
<p>But in the event you access one of your less rigorous colleague’s workbooks and need to see what functions they’ve Frankensteined together, press <code>CTRL + ~</code> to display all the functions instead in the spreadsheet.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728927250678/868f9daa-04d7-447c-b494-15fea77a4e1c.png" alt="display functions in Excel workbook" class="image--center mx-auto" width="807" height="709" loading="lazy"></p>
<h2 id="heading-shortcuts-for-navigation-in-excel">Shortcuts for Navigation in Excel</h2>
<h3 id="heading-keyboard-shortcuts-ctrl-arrow-keys-and-others">Keyboard Shortcuts: <code>CTRL + arrow keys</code> (and others)</h3>
<p>Navigating the grid can be very fast with the keyboard. Pressing <code>CTRL +</code> the <code>arrows</code>, the <code>home</code> and the <code>end</code> buttons will warp you all over the active sheet.</p>
<p>Using the <code>arrows</code> and <code>CTRL</code>, you go to the last nonblank cell in the row or column.</p>
<p>Using <code>CTRL + home or end</code>, you go to the beginning and the end of the workbook, respectively. (When inside a table, <code>home</code> and <code>end</code> take you to the beginning and end of the table only.)</p>
<h2 id="heading-shortcut-to-open-the-autofilter-menu-in-excel">Shortcut to Open the AutoFilter Menu in Excel</h2>
<h3 id="heading-keyboard-shortcut-alt-down-arrow">Keyboard Shortcut: <code>alt + down arrow</code></h3>
<p>Another superpower in Excel is the ease with which we can filter and sort large pieces of data. To access the AutoFilter Menu quickly, press <code>alt + down arrow</code> while in the header for the column you’d like to filter.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728928353490/dcca3af8-2858-4ca0-abd6-d7e197826008.png" alt="auto-filter menu" class="image--center mx-auto" width="444" height="918" loading="lazy"></p>
<h2 id="heading-shortcut-to-create-a-slicer-in-excel">Shortcut to Create a Slicer in Excel</h2>
<h3 id="heading-keyboard-shortcut-alt-n-sf">Keyboard Shortcut: <code>alt + n, sf</code></h3>
<p>For an even more user-friendly method of sorting, you can insert a slicer directly onto the spreadsheet by pressing <code>alt + n, sf</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728928617015/599d1bb7-4873-4f3d-aee2-6d478dcc034c.png" alt="Menu for inserting slicers" class="image--center mx-auto" width="536" height="556" loading="lazy"></p>
<h2 id="heading-shortcut-to-create-checkboxes-in-excel">Shortcut to Create Checkboxes in Excel</h2>
<h3 id="heading-keyboard-shortcut-alt-n-cb">Keyboard Shortcut: <code>alt + n, cb</code></h3>
<p>If you’re anything like me, you’ll find a way to use checkboxes in almost every spreadsheet you create. They’re extremely useful for toggling selections on and off in a workbook, and as of June 2024, Excel has made them available in production Excel.</p>
<p>Press <code>alt + n, cb</code> to insert a checkbox in a cell.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728931963136/cc54e602-2d2c-4536-b07f-408f8404977d.png" alt="cc54e602-2d2c-4536-b07f-408f8404977d" class="image--center mx-auto" width="506" height="467" loading="lazy"></p>
<h2 id="heading-shortcut-to-create-charts-in-excel">Shortcut to Create Charts in Excel</h2>
<h3 id="heading-keyboard-shortcut-alt-n-r">Keyboard Shortcut: <code>alt + n, r</code></h3>
<p>There are a ton of chart types in Excel. To quickly open up the recommended charts dialog box, we can press <code>alt + n, r</code>.</p>
<p>Or, if we know we want a specific type of chart, there are multiple options to shortcut straight to them, like <code>alt + n, C1</code>, <code>alt + n, N1</code>, <code>alt + n, SA</code> and so on.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729001331573/b9e240ba-6f42-4817-9d8c-e27241f66b18.png" alt="Chart types" class="image--center mx-auto" width="911" height="439" loading="lazy"></p>
<h2 id="heading-more-shortcuts">More Shortcuts</h2>
<p>There are a zillion shortcuts available in Excel. If you want to check out the full list, you can find a current version maintained by <a target="_blank" href="https://support.microsoft.com/en-us/office/keyboard-shortcuts-in-excel-1798d9d5-842a-42b8-9c99-9b7213f0040f">Microsoft here</a>.</p>
<h2 id="heading-got-sheet">Got Sheet</h2>
<p>Come join my free newsletter, <a target="_blank" href="https://www.gotsheet.xyz/subscribe">Got Sheet</a>. I show people how to get good at spreadsheets every week.</p>
<p>You can find me over on <a target="_blank" href="https://www.youtube.com/@eamonncottrell">YouTube</a> as well.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Work with Tables in Excel vs Google Sheets ]]>
                </title>
                <description>
                    <![CDATA[ Google Sheets recently released an all new feature: tables. Well, new is a bit of an overstatement. Excel has had proper tables for many, many years, and it's been a point of contention in the spreadsheet community. In this article, I'll break down w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/excel-vs-google-sheets-tables/</link>
                <guid isPermaLink="false">66b8dde70a89d796f29a16dd</guid>
                
                    <category>
                        <![CDATA[ excel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Tue, 02 Jul 2024 17:27:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/4.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Google Sheets recently released an all new feature: tables.</p>
<p>Well, <em>new</em> is a bit of an overstatement. Excel has had proper tables for many, many years, and it's been a point of contention in the spreadsheet community.</p>
<p>In this article, I'll break down what exactly tables are, why they're important, and then see how Google Sheet's new tables stack up against Microsoft Excel's.</p>
<p>Here is a video walkthrough of everything we'll cover:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/vBp5mveYZZ4" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-whats-a-table">What's a Table?</h2>
<p>A table is a way of structuring and formatting data in a spreadsheet. It groups together rows and columns of data so that they can be more easily filtered, grouped, and analyzed.</p>
<p>Many people would look at the following bit of data and wrongly assume that it's already in a table.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-103.png" alt="Image" width="600" height="400" loading="lazy">
<em>Data in Excel</em></p>
<p>This is merely well organized rows and columns of data in Excel. Each column is a separate category of information, that is ids, names, emails, job titles, and salaries.</p>
<p>Each row represents one entry of that data. So, you'd put your id, name, email, job title and salary going left to right in a row.</p>
<p>Simple, yes?</p>
<p>A table contains all the same data, but by formatting it as a table we can unlock a whole lot of additional functionality.</p>
<p>The first of which is the appearance itself. When we create a table, Excel immediately colors our data with a dark header row and bands of alternating colors.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-104.png" alt="Image" width="600" height="400" loading="lazy">
<em>Table in Excel</em></p>
<p>Sheets does the same thing, as we can see below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-105.png" alt="Image" width="600" height="400" loading="lazy">
<em>Table in Google Sheets</em></p>
<p>So, a table is simply a way of managing and grouping data more easily. But it goes much further than just formatting, as we'll see.</p>
<h2 id="heading-why-are-tables-important">Why are Tables Important?</h2>
<p>Tables help reduce errors. When dealing with data, we are always making sure the data is clean and that we don't have errors in our formulas. </p>
<p>Tables help keep things orderly simply by being structured and formatted well. But as we'll see in the formula section in a moment, they also allow us to reduce errors in formulas by dynamically calculating things for us</p>
<h2 id="heading-how-to-create-a-table-in-excel-and-sheets">How to Create a Table in Excel and Sheets</h2>
<p>In Microsoft Excel, creating a table is as easy as clicking anywhere in the data range and pressing <code>CTRL + T</code>. Immediately, Excel will predict the data range for the table and ask you to confirm this.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-106.png" alt="Image" width="600" height="400" loading="lazy">
<em>Excel table data range</em></p>
<p>Alternatively, you can find the same create table option from the Insert Menu in the Ribbon at the top.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/table.png" alt="Image" width="600" height="400" loading="lazy">
<em>Excel insert menu</em></p>
<p>Over in Sheets, you'll need to either right click in a cell in the data range, or select the option from the Format menu to Convert to Table.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/sheets.png" alt="Image" width="600" height="400" loading="lazy">
<em>Convert to table options in Google Sheets</em></p>
<p>One caveat in Sheets: if you right click in a cell, you have to select the whole data range for it to convert to a table. Whereas, if you select Format - Convert to table from the menu, it is (like Excel) smart enough to predict the whole data range.</p>
<p>A small thing. But Excel takes the prize for ease of creation.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/right-click.png" alt="Image" width="600" height="400" loading="lazy">
<em>Convert to table in Google Sheets</em></p>
<p><strong>⭐Winner: EXCEL</strong></p>
<h2 id="heading-how-to-format-tables-in-excel-and-sheets">How to Format Tables in Excel and Sheets</h2>
<p>As we saw initially, some formatting is done as soon as we create a table.</p>
<p>From here, though, both programs allow for further customization.</p>
<p>In Sheets, we can select the dropdown in the top left next to the table name to access a few options immediately. For the most part, we can simply change the alternating colors of the table.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/sheets-format.png" alt="Image" width="600" height="400" loading="lazy">
<em>Formatting options in Google Sheets</em></p>
<p>If we select Custom, it opens up the full alternating colors menu that is also accessible through the Format menu. This gives us more control over the colors, but it's all aesthetic.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-110.png" alt="Image" width="600" height="400" loading="lazy">
<em>Alternating colors menu in Google Sheets</em></p>
<p>Meanwhile in Excel, we have the same options with a few more toggle selections for styling. For instance, we can check the first column to bold the text in the id column or we toggle between banded columns and/or rows.</p>
<p>And on the far right of the Table Design tab in the Ribbon, there are a ton of prebuilt styles that we can toggle on and off.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/format-excel.png" alt="Image" width="600" height="400" loading="lazy">
<em>Table design in Excel</em></p>
<p>Both programs give plenty of options here, and this is mostly to make the tables look good. But Excel comes out on top with more options.</p>
<p><strong>⭐Winner: EXCEL</strong></p>
<h2 id="heading-how-to-sort-tables-in-excel-and-google-sheets">How to Sort Tables in Excel and Google Sheets</h2>
<p>In both programs, there is a dropdown toggle button in each of the header row's cells. Selecting this in Excel allows us to sort ascending or descending...or even by color.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/sort.png" alt="Image" width="600" height="400" loading="lazy">
<em>sort in excel</em></p>
<p>For instance, if we have some of our data using a blue font color, we can actually sort it by that color:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/sort-color.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sort by color in Excel</em></p>
<p>What about Google Sheets? Yep, same deal there. It will also detect when different colors are used and allow you to do the same type of sorting.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/sheets-sorting-options-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sort by color in Sheets</em></p>
<p>Excel does have a Custom Sorting dialog box that can drill down into more detail. For instance, you can add levels of sorting.</p>
<p>Using our color example, we can first sort by the blue font colors in the email color and then by the red font colors in the job title column.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/double-sort.png" alt="Image" width="600" height="400" loading="lazy">
<em>Multiple column sorting in Excel</em></p>
<p>Google Sheets can do the same thing, but not from the header drop downs. The header drop down sorting is restricted to one row at a time in Sheets.</p>
<p>But, if you select the entire table's data range and then <code>Data - Sort Range - Advanced range sorting options</code>, you are able to sort by multiple columns in Google Sheets.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/advanced-sort-google-sheets.png" alt="Image" width="600" height="400" loading="lazy">
<em>Advanced sorting in Google Sheets</em></p>
<p>Sheets' advanced sorting is not as powerful as Excel's, though. You are only able to sort ascending or descending by value. Excel takes the cake on this one by a hair.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/google-sheets-muiltiple-row-sorting.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>⭐Winner: EXCEL</strong></p>
<h2 id="heading-how-to-filter-tables-in-excel-and-google-sheets">How to Filter Tables in Excel and Google Sheets</h2>
<p>Filtering works exactly the same as sorting. In both programs, click the dropdown selector in the header row to see the options for filtering.</p>
<p>In both programs, we have the same options. We can filter by color just like in our sorting. We can filter by values by either selecting all, none, or individual values. And we can filter by condition.</p>
<p>Here's Google Sheet's menu:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-113.png" alt="Image" width="600" height="400" loading="lazy">
<em>Filtering in Google Sheets</em></p>
<p>And here's Excel's menu. All the same options are available. Both programs allow for custom filter formulas to be entered as well.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-112.png" alt="Image" width="600" height="400" loading="lazy">
<em>Filtering in Excel</em></p>
<p><strong>⭐Winner: TIE</strong></p>
<h2 id="heading-how-to-use-tables-in-formulas-in-excel-and-google-sheets">How to Use Tables in Formulas in Excel and Google Sheets</h2>
<p>One of the big reasons to use tables lies in formulas. Whether you use Excel or Sheets, you are likely taking advantage of built-in functions and the ability to create custom formulas for analyzing your data.</p>
<p>By holding your data in a table, your formulas can reference that data dynamically.</p>
<p>Meaning, if you add rows of data to your table, any formulas referencing those table values will update automatically.</p>
<p>The risk of breaking things by adding data decreases dramatically with the use of tables.</p>
<p>Here's a simple example. If we wanted to combine the first and last names into one cell, we could concatenate them with this formula <code>=Salary[first_name]&amp;" "&amp;Salary[last_name]</code>.</p>
<p>In Excel, we reference a table by its name, in this case, <code>Salary</code>. Then within brackets, we reference a column name, <code>[last_name]</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-115.png" alt="Image" width="600" height="400" loading="lazy">
<em>Spill formula in Excel</em></p>
<p>We can do the exact same in Sheets.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-116.png" alt="Image" width="600" height="400" loading="lazy">
<em>Formula referencing in Sheets</em></p>
<p>There's one powerful difference, though. In Excel, the formula will spill down. Meaning, we only have to write it once at the very top, but because it sees that we're referencing values in a table, it will spill down to every row in the table.</p>
<p>In Google Sheets, we still have to drag the formula down.</p>
<p>Now, sometimes, we may not want things to spill down. In this case we can use different syntax in Excel. Instead of the column name within brackets, we can add an @ sign and another set of brackets. This tells Excel to only make the calculation on one row: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-117.png" alt="Image" width="600" height="400" loading="lazy">
<em>Formula referencing in Excel</em></p>
<p>Excel flexes on this one. It's much more powerful to use tables in formulas in Excel than in Sheets.</p>
<p><strong>⭐Winner: EXCEL</strong></p>
<h2 id="heading-how-to-change-table-range-in-excel-and-google-sheets">How to Change Table Range in Excel and Google Sheets</h2>
<p>What if we want to extend our table or remove data from it? Both Google Sheets and Excel allow us to do this easily.</p>
<p>Say we want to add a column for the full name of a person. In both programs, if we simply type in <code>full_name</code> in G1 to the right of our last column, that column will become a part of the table's data range.</p>
<p>Anytime we type in an adjacent column or row to our table data, the programs will assume the table needs to extend to include it.</p>
<p>Then, we can use a version of the formula from our previous example to insert the full names. Now that we are inside of the table, though, it's not necessary to include the title of the table in our formula.</p>
<p>Now, all that's needed in Excel is <code>=[@[first_name]]&amp;" "&amp;[@[last_name]]</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-119.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reference table columns in Excel</em></p>
<p>For Google Sheets, it's the same inside the table as outside it: <code>=Table2[first]&amp;" "&amp;Table2[last]</code>. Sheets also requires us to drag the formula down. It does not handle spilling like Excel (yet).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-118.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reference table columns in Sheets</em></p>
<p>To add columns within a table, we can right click the column name and select insert.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-120.png" alt="Image" width="600" height="400" loading="lazy">
<em>Insert column in Excel</em></p>
<p>Google has a slight edge here in that you can select whether to insert to the left or the right, whereby Excel only inserts to the left.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-121.png" alt="Image" width="600" height="400" loading="lazy">
<em>Insert column Google Sheets</em></p>
<p>Inserting rows is exactly the same. Excel allows for inserting rows above, while Sheets allows you to select above or below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-122.png" alt="Image" width="600" height="400" loading="lazy">
<em>Inserting rows Google Sheets</em></p>
<p>In both programs, deleting rows and columns is as simple as selecting the row(s) or column(s), right clicking, and selecting delete.</p>
<p>In Excel you have the added benefit of a keyboard shortcut. <code>CTRL + -</code> will delete the selected rows or columns.</p>
<p>Both programs will also allow you to convert a table back to a regular data range. In Excel, it's the <code>Convert to Range</code> button in the <code>Table Design</code> tab of the menu</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/convert.png" alt="Image" width="600" height="400" loading="lazy">
<em>Convert to Range option in Excel</em></p>
<p>And in Google Sheets, it's the <code>Revert to unformatted data</code> option from the table dropdown menu.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/revert.png" alt="Image" width="600" height="400" loading="lazy">
<em>Revert to unformatted data option in Sheets</em></p>
<p><strong>⭐Winner: TIE</strong></p>
<h2 id="heading-how-to-add-a-total-row-in-a-table">How to Add a Total Row in a Table</h2>
<p>There's a good chance you'll want to total up the amounts in a column. How easy is this to add in a table?</p>
<p>You can do it in both programs, but...</p>
<p>Excel makes it incredibly easy. There's a toggle option for this in the Table Design menu in the Ribbon. Toggle this on, and a Total row is automatically included and calculated at the bottom.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/total-row.png" alt="Image" width="600" height="400" loading="lazy">
<em>Total row in Excel</em></p>
<p>Can you do the same in Sheets? </p>
<p>Yes, you've just got to do it yourself.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-124.png" alt="Image" width="600" height="400" loading="lazy">
<em>Total row in Sheets</em></p>
<p><strong>⭐Winner: EXCEL</strong></p>
<h2 id="heading-who-wins">Who Wins?</h2>
<p>Well, it's no surprise that Excel comes out on top. Sheets users (myself included) have a lot to be excited about with the ability to finally create proper tables. By and large, the functionality is just as powerful as Excel. </p>
<p>And much like many features compared between the two programs, Sheets can probably get the job done for most use cases.</p>
<p>Excel, as per normal, simply does more and does it a little bit better.</p>
<p>I'm Eamonn, and I'll help you <strong>get good at spreadsheets</strong>. Join my free newsletter, <a target="_blank" href="https://www.gotsheet.xyz/subscribe">Got Sheet, here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Pop-up Image in Your Spreadsheet ]]>
                </title>
                <description>
                    <![CDATA[ In this article, I'll show you two ways to create a lightbox effect in a spreadsheet. The first will trigger the image to be displayed in a large area in the sheet. The second will be an actual HTML popup on top of the sheet. If you want to follow ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-an-image-lightbox/</link>
                <guid isPermaLink="false">66b8de0647c23b7ae1ad0bc0</guid>
                
                    <category>
                        <![CDATA[ google apps script ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Thu, 16 May 2024 10:17:53 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/Lightbox-2-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, I'll show you two ways to create a lightbox effect in a spreadsheet. The first will trigger the image to be displayed in a large area in the sheet. The second will be an actual HTML popup on top of the sheet.</p>
<p>If you want to follow along with the sheet I used, you can access it <a target="_blank" href="https://docs.google.com/spreadsheets/d/1Uz9sZJW1ts_YZc2-Ifd-UAQ8Pkgn23XLzmNdE_sDYrg/copy">here</a>. The link will prompt you to create a copy of the spreadsheet and accompanying Apps Script file.</p>
<h2 id="heading-what-is-an-image-lightbox">What is an Image Lightbox?</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-35.png" alt="Image" width="600" height="400" loading="lazy">
<em>image thumbnails in a spreadsheet</em></p>
<p>An image lightbox is what we call it when we hover over or click on an image and it pops up into a bigger version on-screen.</p>
<p>It’s something we’re used to seeing on websites, and it gives things a nice, professional touch when done well.</p>
<p>What about in a spreadsheet, though? 🤔</p>
<p>Well, we’ve got two versions of a solution:</p>
<ol>
<li>Using built-in functions to display a larger version in a larger cell.</li>
<li>Using Apps Script to actually create a popup box on top of our spreadsheet.</li>
</ol>
<p>As a bonus to the first solution, we’ll also include optional Apps Script to make things a little smoother. More on that below 😉.</p>
<p>As usual, here's a walkthrough video where I go through the whole process:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/J39nMbuycEk" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-image-popup-with-built-in-functions">Image Popup With Built-In Functions</h2>
<p>First, we need images in cells. From the top menu, <code>Insert - Image - Insert image in cell</code> will do the trick for this.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-37.png" alt="Image" width="600" height="400" loading="lazy">
<em>inserting image in spreadsheet cell</em></p>
<p>Next, we need to merge some cells together so that there’s a larger container that will hold our larger picture after the next step.</p>
<p>You can use one cell and change the width and height of it, but in my <a target="_blank" href="https://docs.google.com/spreadsheets/d/1Uz9sZJW1ts_YZc2-Ifd-UAQ8Pkgn23XLzmNdE_sDYrg/copy">example sheet</a>, the “lightbox” area is sharing rows with the rest of the data so I didn’t want to do that.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-38.png" alt="Image" width="600" height="400" loading="lazy">
<em>a large range of merged cells</em></p>
<p>In the column next to my image thumbnails, I’ve put checkboxes by selecting <code>Data - Data validation - Criteria: Checkboxes</code> from the top menu.</p>
<p>This will let us select which image to popup in our lightbox area.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-39.png" alt="Image" width="600" height="400" loading="lazy">
<em>data validation in google sheets</em></p>
<p>I’ve named the range <code>A2:A11</code> as <code>pics</code> and the range <code>B2:B11</code> as <code>checkboxes</code> to allow for easier readability in the function we’ll write next.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-41.png" alt="Image" width="600" height="400" loading="lazy">
<em>named ranges in google sheets</em></p>
<p>Now all that remains is one <code>XLOOKUP()</code> function to put inside our lightbox range.</p>
<p><code>=XLOOKUP(TRUE,checkboxes,pics,"")</code> is the function that searches for a check and then displays the corresponding image. By putting this in a big cell or range of merged cells, we can display whichever small image we select in the bigger area.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-40.png" alt="Image" width="600" height="400" loading="lazy">
<em>xlookup function in google sheets</em></p>
<p>Remember, all a checkbox is doing is storing either a <code>TRUE</code> (checked) or a <code>FALSE</code> (unchecked) value.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-42.png" alt="Image" width="600" height="400" loading="lazy">
<em>checkboxes and image thumbnails in google sheets</em></p>
<h2 id="heading-warning">⚠️WARNING⚠️</h2>
<p>This does have one issue, though. Do you know what it is?</p>
<p><code>XLOOKUP()</code> is going to return whichever checkboxes it comes to first with a TRUE value. So if you have multiple images checked, it’s only going to display the <em>first one it gets to</em>, not the most <em>recently clicked</em> one.</p>
<p>To get around this, let’s write some code.</p>
<h2 id="heading-apps-script-improvement">Apps Script Improvement</h2>
<p>Open up Apps Script by selecting <code>Extensions - Apps Script</code> from the top menu.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-46.png" alt="Image" width="600" height="400" loading="lazy">
<em>opening apps script in google sheets</em></p>
<p>Delete the built-in function in the code editor that opens. We'll start from scratch with an <code>onEdit</code> function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">onEdit</span>(<span class="hljs-params">e</span>) </span>{
</code></pre>
<p>We need to grab the range that we are currently editing.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> range = e.range
</code></pre>
<p>Then the checkboxes range.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> checkboxes = SpreadsheetApp.getActive().getRangeByName(<span class="hljs-string">"checkboxes"</span>)
</code></pre>
<p>Then we need to check whether what we just edited is in that checkbox range.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (range.getColumn() == <span class="hljs-number">2</span> &amp;&amp; range.getRow() &gt;= <span class="hljs-number">2</span> &amp;&amp; range.getRow() &lt;= <span class="hljs-number">10</span>)
</code></pre>
<p>If it was a checkbox, then we want to uncheck all the checkboxes and re-check the one we just checked.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Uncheck all other checkboxes in the range</span>
checkboxes.uncheck();
<span class="hljs-comment">// Check the edited cell</span>
range.check();
</code></pre>
<p>Now, there is a slight delay when you run the code. After clicking a checkbox, all of them are cleared right before the one you checked gets checked again.</p>
<p>Here’s what the full code looks like:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">onEdit</span>(<span class="hljs-params">e</span>) </span>{
  <span class="hljs-keyword">var</span> range = e.range;
  <span class="hljs-keyword">var</span> checkboxes = SpreadsheetApp.getActive().getRangeByName(<span class="hljs-string">"checkboxes"</span>)

  <span class="hljs-comment">// Check if the edited cell is a checkbox in the desired range</span>
  <span class="hljs-keyword">if</span> (range.getColumn() == <span class="hljs-number">2</span> &amp;&amp; range.getRow() &gt;= <span class="hljs-number">2</span> &amp;&amp; range.getRow() &lt;= <span class="hljs-number">10</span>) {
    <span class="hljs-comment">// Uncheck all other checkboxes in the range</span>
    checkboxes.uncheck();
    <span class="hljs-comment">// Check the edited cell</span>
    range.check();
  }
}
</code></pre>
<h2 id="heading-a-real-popup-box-with-html">A Real Popup Box with HTML</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-43.png" alt="Image" width="600" height="400" loading="lazy">
<em>modal dialog box in google sheets</em></p>
<p>Okay, that’s all fine and dandy. What about the real thing, though?</p>
<p>This takes more Apps Script, but it’s doable thanks to the built-in <code>howModalDialog</code> method.</p>
<p>This is basically a popup window that can hold HTML. And since the internet is built with HTML, all we need to do is use a little bit to plug in an image.</p>
<p>This method requires an image live on the internet somewhere. So, we cannot reference the image that we've embedded in our sheet and use it in the HTML we're going to write.</p>
<p>Weird, I know.</p>
<p>Let’s find an image URL we can use. I’ve grabbed an eagle off of <a target="_blank" href="https://unsplash.com/">unsplash</a>.</p>
<p>We’ll hold this in a variable.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> imageURL = <span class="hljs-string">"https://images.unsplash.com/photo-1715002383611-63488b956401?q=80&amp;w=1887&amp;auto=format&amp;fit=crop&amp;ixlib=rb-4.0.3&amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"</span>
</code></pre>
<p>Then we need to build our HTML. In our case, all we want is one element, so we won’t worry ourself with constructing a full, semantically correct page (although we certainly could 😉)</p>
<p>Another variable will hold this <code>img</code> element:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> html = <span class="hljs-string">'&lt;img src="'</span> + imageURL + <span class="hljs-string">'" style="max-width: 100%; max-height: 100%;"&gt;'</span>;
</code></pre>
<p>We have access to <a target="_blank" href="https://developers.google.com/apps-script/reference/base/ui">Class Ui</a> in Apps Script where we can “…add features like menus, dialogs, and sidebars.”</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">var</span> ui = SpreadsheetApp.getUi();
</code></pre>
<p>And finally, by calling the <code>showModalDialog()</code> method, we can generate HTML from our <code>html</code> variable using the <a target="_blank" href="https://developers.google.com/apps-script/reference/html/html-service">Class HtmlService</a>.</p>
<pre><code class="lang-javascript">ui.showModalDialog(HtmlService.createHtmlOutput(html).setWidth(<span class="hljs-number">700</span>).setHeight(<span class="hljs-number">1000</span>), <span class="hljs-string">'Eagle 🦅'</span>);
</code></pre>
<p>A final touch is to add a thumbnail version of our eagle image into our spreadsheet so that it is inserted on top of our cells (this next bit won’t work if it’s embedded in a cell itself).</p>
<p>Once it’s in our sheet, we can click the three black dots in the top right corner and assign a script directly to the image.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-44.png" alt="Image" width="600" height="400" loading="lazy">
<em>assigning a script to image in google sheets</em></p>
<p>We named our script <code>displayImagePopup</code>, so this is what we enter. Make sure to leave off the parentheses when typing it into the image's script form.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-45.png" alt="Image" width="600" height="400" loading="lazy">
<em>assigning script</em></p>
<p>Now, anytime we click the small image of the eagle, a popup box opens with the full image.</p>
<p>Here’s what the full code looks like:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">displayImagePopup</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Get the active sheet</span>
  <span class="hljs-keyword">var</span> sheet = SpreadsheetApp.getActiveSheet();
  <span class="hljs-keyword">var</span> imageURL = <span class="hljs-string">"https://images.unsplash.com/photo-1715002383611-63488b956401?q=80&amp;w=1887&amp;auto=format&amp;fit=crop&amp;ixlib=rb-4.0.3&amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"</span>
  <span class="hljs-comment">// Create an HTML string for the popup</span>
  <span class="hljs-keyword">var</span> html = <span class="hljs-string">'&lt;img src="'</span> + imageURL + <span class="hljs-string">'" style="max-width: 100%; max-height: 100%;"&gt;'</span>;

  <span class="hljs-comment">// Show the dialog</span>
  <span class="hljs-keyword">var</span> ui = SpreadsheetApp.getUi();
  ui.showModalDialog(HtmlService.createHtmlOutput(html).setWidth(<span class="hljs-number">700</span>).setHeight(<span class="hljs-number">1000</span>), <span class="hljs-string">'Eagle 🦅'</span>);
}
</code></pre>
<h2 id="heading-thank-you-so-much">Thank you so much!</h2>
<p>I hope this was helpful for you. </p>
<p>Check out my <a target="_blank" href="https://www.youtube.com/@eamonncottrell">YouTube channel</a> and <a target="_blank" href="https://www.gotsheet.xyz/subscribe">free newsletter</a> to get good at spreadsheets!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Advanced Google Sheets Concepts – How to Build a Vigenère Cipher ]]>
                </title>
                <description>
                    <![CDATA[ A Vigenère Cipher encrypts and decrypts text using a different alphabet for each letter. It consists of text to encrypt and a key with a different letter corresponding to each letter in the text.  Creating a grid of alphabets helps illustrate this pr... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/advanced-google-sheets-concepts-build-a-vigenere-cipher/</link>
                <guid isPermaLink="false">66b8ddc90a89d796f29a16d9</guid>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Wed, 13 Dec 2023 18:13:22 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/12/2cipher.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A Vigenère Cipher encrypts and decrypts text using a different alphabet for each letter. It consists of text to encrypt and a key with a different letter corresponding to each letter in the text. </p>
<p>Creating a grid of alphabets helps illustrate this practice. If the first letter in your text is <code>A</code> and the first letter in your key is <code>L</code>, you would find the encrypted letter, <code>L</code>, where the plaintext and key intersect:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/cipher2.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of a grid of alphabets</em></p>
<p>So your text to encrypt might look like this: <code>attackatdawn</code>, your key might be this: <code>LEMONLEMONLE</code>, and the ciphertext would be this: <code>LXFOPVEFRNHR</code>.</p>
<p>This is the same example used on the <a target="_blank" href="https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher">Wikipedia page</a> which I'll walk you through in this article.</p>
<p>You could create a cipher encoder/decoder with any number of programming languages. But spreadsheets are a nice tool to use for this kind of project because they come with some pretty robust built-in functions that will help us dissect the cipher. </p>
<p>I've chosen Google Sheets because it's a hair simpler to jump into, especially if you already have a Gmail account. But you can do all the same things in Microsoft Excel.</p>
<p>Here's the <a target="_blank" href="https://docs.google.com/spreadsheets/d/1i_auliGPhTOIOk3WrsIRuHveXyEdQxi16BcvSBo6MTA/edit#gid=1257498594">Google Sheet I used</a>.</p>
<p>If you'd like to check out a video walkthrough, here you go 👇</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/dM_Ims4KnVc" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-spreadsheet-preparation">Spreadsheet Preparation</h2>
<p>This isn't too complicated. We need a grid of alphabets. No, you don't have to type them in over and over, either.</p>
<p>In fact, you don't even have to type the whole first alphabet. Let's use Unicode characters. For capital letters, the Unicode for the alphabet starts with 65. </p>
<p>The <code>CHAR()</code> function in spreadsheets converts a number into a character according to the current Unicode table.</p>
<p>The <code>COLUMN()</code> function returns a number corresponding to the current column where column A returns 1, column B returns 2, and so on. </p>
<p>So if we start our alphabet in column B, we can access each letter by adding 63 to the <code>COLUMN()</code> function and wrapping it in the <code>CHAR()</code> function:</p>
<pre><code>=CHAR(COLUMN()+<span class="hljs-number">63</span>)
</code></pre><p>Then we can drag this over to the right until we've got the full alphabet.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/image-41.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of CHAR and COLUMN functions</em></p>
<p>The same thing applies going down. We'll just use the <code>ROW()</code> function instead:</p>
<pre><code>=CHAR(ROW()+<span class="hljs-number">63</span>)
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2023/12/image-42.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of CHAR and ROW functions</em></p>
<p>Then we can reference the cell above and to the right for every cell below to fill out the full alphabet grid:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/image-43.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of spreadsheet cell</em></p>
<p>The only one that will be different will be in the last column where we'll need to reference the first column to have the alphabet wrap:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/image-44.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of spreadsheet cell</em></p>
<p>We only have to do this on the second line. Then, select the full second row and drag the formulas down to fill out the grid:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/drag.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of spreadsheet grid</em></p>
<p>At this point, you can copy <code>CTRL + C</code> and paste values only <code>CTRL + SHIFT + V</code> for all the alphabet. If you add or shift rows, the alphabets may get skewed since their formulas reference fixed columns.</p>
<h2 id="heading-the-game-plan">The Game Plan</h2>
<p>Now the fun stuff. We want our text to be encrypted automatically. Let's highlight three cells: one for the text to encrypt, one for a key, and then a blank cell for our encrypted text:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/image-46.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of text to encrypt</em></p>
<p>Note: the key needs to be the same length as the text to encrypt/decrypt. In this example, the key is the word LEMON, but we extend it by repeating it for every character we need to encrypt.</p>
<p>Now we need to do three things: </p>
<ol>
<li>Split out each character of our text into its own cell</li>
<li>Loop through each character and encrypt it based on the corresponding key character.</li>
<li>Join all those characters together and place the result in our encrypted text cell.</li>
</ol>
<h2 id="heading-split-text-to-setup">Split Text to Setup</h2>
<p>Interestingly, we cannot use the <code>SPLIT()</code> - or if you're in Excel, the <code>TEXTSPLIT()</code> - function without a delimiter. That is, we can't just tell it to split each character without there being something in between the characters.</p>
<p>So, we have to get fancy. In the video walkthrough, I explore a Google Sheets-specific approach using regular expressions...which are hard fun.</p>
<p>Here's what it looks like, and it involves creating character groups, inserting something in between each one, and then splitting using that same something as the delimiter. I used a blank space as the thing which I inserted and then split by:</p>
<pre><code>=SPLIT(REGEXREPLACE(AG6,<span class="hljs-string">"(.)"</span>,<span class="hljs-string">"$1 "</span>),<span class="hljs-string">" "</span>)
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2023/12/hard.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of woman saying, that's just hard</em></p>
<p>Excel users and mortals, fear not – there's a more elegant way that I'll show you here that can be done in either program by using the <code>MID()</code> and <code>COLUMNS()</code> functions.</p>
<p>The <code>MID()</code> function extracts a segment of a string, and <code>COLUMNS()</code> returns the number of columns in an array. By nesting <code>COLUMNS()</code> inside <code>MID()</code> we can one by one extract each character from the string:</p>
<pre><code>=MID($AG$<span class="hljs-number">6</span>,COLUMNS($AG6:AG6),<span class="hljs-number">1</span>)
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2023/12/image-47.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of MID and COLUMNS functions</em></p>
<p>By locking <code>$AG6</code> as the first part of the array referenced in the <code>COLUMNS()</code>  function, this number adds one for every column we drag our formula over.</p>
<p>Drag this over until you reach the end of the text to encrypt. Every character should be in its own cell now. Do the same for the key.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/image-48.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of spreadsheet cells</em></p>
<h2 id="heading-how-to-use-xlookup-to-encrypt">How to Use <code>XLOOKUP()</code> to Encrypt</h2>
<p>Below each pairing of plaintext and key text, we will now do a double <code>XLOOKUP()</code>. </p>
<p>Yes, it's as awesome as it sounds.</p>
<p>Here's what it looks like, and let's walkthrough what's happening:</p>
<pre><code>=XLOOKUP(AD9,<span class="hljs-attr">$B$2</span>:$B$<span class="hljs-number">27</span>,XLOOKUP(AD10,<span class="hljs-attr">$B$2</span>:$AA$<span class="hljs-number">2</span>,<span class="hljs-attr">$B$2</span>:$AA$<span class="hljs-number">27</span>))
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2023/12/image-49.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of double XLOOKUP functions</em></p>
<p>For the beginning <code>XLOOKUP()</code>, we are looking up the plaintext and we're referencing the first plaintext alphabet for our lookup range. But then for our result range, we're opening up another <code>XLOOKUP()</code>...</p>
<p>This is because we still have to use the correct key alphabet to return an encrypted value.</p>
<p>So, we need the second <code>XLOOKUP()</code> to return a full alphabet based on the position of the key character.</p>
<p>We're using the key character as our lookup value, we're using the first alphabet along the top key row for our lookup range, and then we're returning the whole grid as our result range. This will let us return a full alphabet which is in turn referenced as the result range for our first <code>XLOOKUP()</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/cipher3.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of alphabet grid and XLOOKUP example</em></p>
<p>You can see the second <code>XLOOKUP()</code> by itself in the picture above. The formula is in the top left. We're using the first letter of key text as the lookup value. The lookup range is the top alphabet in the purple box. The result range is the whole grid in the blue box. And the returned alphabet is the one that starts with L in the red box.</p>
<p>You can see it being returned underneath the formula where there is an arrow in the picture.</p>
<p>Drag the double <code>XLOOKUP()</code> function over to encrypt every character of the plaintext with the key text.</p>
<h2 id="heading-join-text-for-final-solution">Join Text for Final Solution</h2>
<p>Now that we've encrypted each letter, we want them to be joined into one string and returned in our encrypted text cell.</p>
<p>To do this, we can use the <code>JOIN()</code> function - or <code>TEXTJOIN()</code> for Excel - with an empty quote as the delimiter. </p>
<pre><code>=JOIN(<span class="hljs-string">""</span>,<span class="hljs-attr">AD11</span>:AO11)
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2023/12/image-50.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of JOIN function</em></p>
<p>And voilà! We've just encrypted a string using a double <code>XLOOKUP()</code>.</p>
<h2 id="heading-how-to-decrypt-text">How to Decrypt Text</h2>
<p>Decryption works exactly the same. The only difference is the placement of the second <code>XLOOKUP()</code>. Instead of using it as the result range, we're using it as the lookup range:</p>
<pre><code>=XLOOKUP(AD20,XLOOKUP(AD21,<span class="hljs-attr">$B$2</span>:$AA$<span class="hljs-number">2</span>,<span class="hljs-attr">$B$2</span>:$AA$<span class="hljs-number">27</span>),<span class="hljs-attr">$B$2</span>:$B$<span class="hljs-number">27</span>)
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2023/12/image-51.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of decryption double XLOOKUP example</em></p>
<h2 id="heading-thanks-for-reading">Thanks for reading</h2>
<p>I hope this was helpful for you and that you learned something new!</p>
<p>You can find more of my tutorials on <a target="_blank" href="https://www.youtube.com/@eamonncottrell">YouTube</a>, and please sign up for my newsletter about <a target="_blank" href="https://got-sheet.beehiiv.com/">coding and spreadsheets here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add Numbers in Excel ]]>
                </title>
                <description>
                    <![CDATA[ Did you know you can write Python code in a spreadsheet? You'd be surprised how many different ways there are to do things in Excel. Below, I'll show you 9 ways to add two or more numbers. You can skip to a certain section if you'd like to see that ]]>
                </description>
                <link>https://www.freecodecamp.org/news/add-numbers-in-excel/</link>
                <guid isPermaLink="false">66b8ddc62755c964523f056c</guid>
                
                    <category>
                        <![CDATA[ excel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Math ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Thu, 12 Oct 2023 21:02:58 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/add-numbers-thumb-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Did you know you can write Python code in a spreadsheet?</p>
<p>You'd be surprised how many different ways there are to do things in Excel. Below, I'll show you 9 ways to add two or more numbers. You can skip to a certain section if you'd like to see that method:</p>
<ol>
<li><a class="post-section-overview" href="#">Manual</a></li>
<li><a class="post-section-overview" href="#-1">References</a></li>
<li><a class="post-section-overview" href="#-2">SUM()</a></li>
<li><a class="post-section-overview" href="#-3">SUMIF()</a></li>
<li><a class="post-section-overview" href="#-4">SUBTOTAL()</a></li>
<li><a class="post-section-overview" href="#-5">AGGREGATE()</a></li>
<li><a class="post-section-overview" href="#-6">VBA</a></li>
<li><a class="post-section-overview" href="#-7">Python</a></li>
<li><a class="post-section-overview" href="#-8">Highlight</a></li>
</ol>
<h2 id="heading-video-walkthrough">Video Walkthrough</h2>
<p>If you prefer to watch me go through each of these in a demo workbook, here's a video for that:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/xe5Ohlgizi8" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>To write a formula or a function in Excel (which we'll be doing in the examples below), start out by simply typing an equals sign in a cell.</p>
<p><code>=</code></p>
<p>This triggers Excel to know that what follows will be a formula or a built-in function.</p>
<p><a id="manual"></a></p>
<h2 id="heading-manual">Manual</h2>
<p>This is simplest version of a formula in Excel. Start out with the equals sign, and then type in the numbers and operation you want to do. Just like a calculator:</p>
<p><code>=6+102</code></p>
<p>Pressing enter will result in <code>108</code> being listed in the cell</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-30.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of manual addition in Excel</em></p>
<p><a id="reference"></a></p>
<h2 id="heading-references">References</h2>
<p>The next step up in Excel is to start using cell references. Notice that on the top and on the left side of the main spreadsheet area, there are columns designated by letters and rows designated by numbers.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/rowscolumns.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of rows and columns</em></p>
<p>We can refer to specific cells using "A1" notation. Like a set of (x,y) coordinates on a graph, this simply means that by referring to C4, for instance, we are referring to the cell found in column C, row 4.</p>
<p>To add numbers using references, we start again with the equals sign and refer to the values in specific cells directly.</p>
<p>This has the added advantage of being dynamic. If a value is changed in one of the cells, the result of the sum automatically updates.</p>
<p><code>=SUM(A1+A3)</code> provides us with the value of the numbers in <code>A1</code> and <code>A3</code>.</p>
<p><a id="sum"></a></p>
<h2 id="heading-sum">SUM()</h2>
<p>The first two methods are examples of using formulas. We manually give Excel a series of instructions that it executes. </p>
<p>Excel also has built-in functions which we can use by starting with the equals sign and then referring to the function by name. Functions also take variables which we pass to them by using a set of parenthesis after the name of the function.</p>
<p>The <code>SUM()</code> function takes either a range or a comma-separated list of cell references. It then returns the sum of all the numbers in the range. </p>
<p>You can select a range by either clicking and dragging or by declaring one by typing in the A1 notation with a colon in between the top left cell and the bottom right cell of the range.</p>
<p><code>SUM(A5:A11)</code> adds all the numbers in cells <code>A5, A6, A7, A8, A9, A10, A11</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-31.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of the SUM() function</em></p>
<p><a id="sumif"></a></p>
<h2 id="heading-sumif">SUMIF()</h2>
<p>A more powerful version of <code>SUM()</code> is the <code>SUMIF()</code> function. This adds conditional logic. It needs at least two variables: a range and a condition. We could give it the same range as above and have a condition be that it only adds up numbers that are greater than zero.</p>
<p>A third, optional variable is a <code>sum_range</code>. This allows for us to match a condition in one range with the sum of values in another range.</p>
<p>In the example sheet, I have inserted checkboxes in column C. Checkboxes in Excel are <a target="_blank" href="https://youtu.be/hROvLovbl8E">a new feature</a>. This is the range that I'm checking for a condition. The condition is TRUE. Now I enter the range that I want to sum if the condition in the corresponding row of the first range is indeed TRUE.</p>
<p>When using a range and a sum_range separately like this, they do have to be of the same size or it will not behave as you want it to.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-32.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of SUMIF() function in Excel</em></p>
<p><a id="subtotal"></a></p>
<h2 id="heading-subtotal">SUBTOTAL()</h2>
<p>Ok, here's where things start to get interesting.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/butts.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The <code>SUBTOTAL()</code> function allows us to do a ton of different things. Ultimately, it returns a subtotal of a list or database. But inside of <code>SUBTOTAL()</code> there are other functions. The first argument that we give <code>SUBTOTAL()</code> is a number corresponding to one of these functions:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-33.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of functions within SUBOTAL from Microsoft Excel</em></p>
<p>Looking at the function list, we see that 9 or 109 both correspond to the <code>SUM()</code> function which we want to use. If we have hidden rows in our range that we don't want to include in the sum, we use 109 to ignore those – if not, simply 9.</p>
<p>So the function looks like this: <code>SUBTOTAL(9,B3:B12)</code>. This sums <code>B3:B12</code> even if one or more of those rows are hidden.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-34.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of SUBTOTAL in Excel</em></p>
<p><a id="aggregate"></a></p>
<h2 id="heading-aggregate">AGGREGATE()</h2>
<p>We can think of <code>AGGREGATE()</code> as a souped-up version of <code>SUBTOTAL()</code>. It works in the same way but has a lot more built-in functions (19 of them) and allows for detailed specificity on what values, if any, to ignore in the calculation.</p>
<p><code>AGGREGATE(function_num, options, ref1, [ref2], …)</code> is the full reference formula. Again, we pass it a number corresponding to one of the 19 built-in functions, then an optional argument for what type of values to ignore, followed by the reference array and an optional second reference array.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-35.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of options for Aggregate function from Microsoft Excel</em></p>
<p>For our example, we again use 9 as our function number, but we can use option 5 to explicitly exclude hidden rows:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-36.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of Aggregate function in Excel</em></p>
<p><a id="vba"></a></p>
<h2 id="heading-vba">VBA</h2>
<p>Now we're warmed up. Let's get overly complicated.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/complicated.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of complicated nonsense</em></p>
<p>Visual Basic for Applications is Microsoft's baked-in programming language in Microsoft Office applications.</p>
<p>Open it up by selecting Visual Basic from the Developer tab. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/vba.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of VBA in Developer tab in Excel</em></p>
<p>If you don't see the developer tab, go to File - Options - Customize Ribbon and add it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/developer-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of Customizing Ribbon in Excel</em></p>
<p>Also, <code>Alt +11</code> is the keyboard shortcut to open up VBA.</p>
<p>Once here, we can write code to do all sorts of things. Our example isn't very practical since a function will do it quicker, but the following code will Sum the range <code>A1:A11</code>, put the result in <code>F11</code> and display a message pop-up with the result:</p>
<pre><code class="lang-vba">Sub AssignSumVariable()
   Dim result As Double
   'Assign the variable
   result = WorksheetFunction.Sum(Range("B1:B11"))
   'Show the result
   MsgBox "The total of the ranges is " &amp; result
   'Put the result in cell F9
  Range("F9") = result
End Sub
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-37.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of VBA in Excel</em></p>
<p><a id="python"></a></p>
<h2 id="heading-python">Python</h2>
<p>Yes, this is now ridiculous. But, it's good to know what Excel can do when you have more complicated tasks that require tools like VBA or Python. At the time of this writing, Python is available in Excel for people using the Beta Channel of Excel.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/overkill.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of woman saying "seems like overkill"</em></p>
<p>You can check your eligibility and join Microsoft 365 Insider if you want to test out new features like this in the future.</p>
<p>Go to File - Account, and then select the 365 Insider channel button for more info.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-38.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of Microsoft 365 Insider options</em></p>
<p>Once Python is usable in Excel, you activate it by typing <code>=py</code> and then the <code>tab</code> key. This turns the cell into a Python command line.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-39.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of Python command line in Excel</em></p>
<p>From here, we can write Python code directly in the cell. The following code uses the custom xl() function for Python to use a range. We hold the range in the numbers variable and then using dot notation, we sum that range with the <code>numbers.sum()</code> line:</p>
<pre><code class="lang-python">numbers = xl(<span class="hljs-string">"'Sum➕'!$B$3:$B$12"</span>)
numbers.sum()
</code></pre>
<p>Now to execute the Python code, click <code>CTRL + ENTER</code>.</p>
<p>What we now see is that we've got a Python Series in the cell:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-40.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In order to just display the answer, we can click the Python Output selector just to the left of the formula bar and select <code>Excel Value</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/python-object.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of Python Output in Excel</em></p>
<p>Now, our cell is updated with the correct value.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-42.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of cells in Excel</em></p>
<p>The real value of Python in Excel comes with manipulating dataframes using built-in libraries like Matplotlib, NumPy, or Pandas.</p>
<p>Okay, take a breath, we'll finish with something simple and easy...👇</p>
<p><a id="highlight"></a></p>
<h2 id="heading-highlight">Highlight</h2>
<p>Bonus time. If you highlight cells in Excel by either clicking and dragging mouse over a range, or by <code>CTRL</code>+ <code>Left-Click</code> individual cells, some automatic calculations are visible in the bottom right of the window, including the Average, Count and Sum:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/highlight.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If the sum isn't immediately visible, right clicking will pull up auto-calculations that you can toggle on and off:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-29.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of auto-calculation options in Excel</em></p>
<h2 id="heading-thanks-for-reading">Thanks for reading!</h2>
<p>Hope this is helpful for you!</p>
<p>Follow me on LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/eamonncottrell/">https://www.linkedin.com/in/eamonncottrell/</a></p>
<p>And YouTube: <a target="_blank" href="https://www.youtube.com/@eamonncottrell">https://www.youtube.com/@eamonncottrell</a></p>
<p>Have a great one! 👋</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Google Sheets – A Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ Google Sheets is an online spreadsheet app with real-time collaboration features. It's like Microsoft Excel for regular people. 🙌 gif of guy saying aren't ordinary people adorable And, these days, it's actually giving Excel a run for its money. It'... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/google-sheets-for-beginners/</link>
                <guid isPermaLink="false">66b8ddef0a89d796f29a16e1</guid>
                
                    <category>
                        <![CDATA[ beginners guide ]]>
                    </category>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Tue, 25 Jul 2023 17:53:57 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/07/maxresdefault.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Google Sheets is an online spreadsheet app with real-time collaboration features. It's like Microsoft Excel for regular people. 🙌</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/ordinary.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of guy saying aren't ordinary people adorable</em></p>
<p>And, these days, it's actually giving Excel a run for its money. It's picked up a lot of features and processing power over the years that used to be exclusive to Excel.</p>
<p>But we're here to talk about the basics today.</p>
<p>🧾I'm going to cover:</p>
<ol>
<li>How to create new Google Sheets</li>
<li>Intro to Templates</li>
<li>Menu and toolbar overview</li>
<li>Basic data entry and calculations</li>
<li>Basic formatting</li>
<li>How to create a table</li>
<li>How to sort and filter data</li>
<li>Intro to formulas and functions</li>
</ol>
<h2 id="heading-video-walkthrough">Video Walkthrough</h2>
<p>I've made a video walkthrough of the things we'll be covering in this article. You can check it out below:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/_bvRa7T-59U" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-how-to-create-a-new-sheet">How to Create a New Sheet</h2>
<p>Spreadsheets can be intimidating even in their most basic form. </p>
<p>Don't be scared, though.👇 </p>
<p>To use Google Sheets, you need a free Google account. (If you're using Gmail, you already have this.) Go <a target="_blank" href="https://www.google.com/sheets/about/">here</a> to sign up if you don't have one yet.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-141.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of the Google Sheets homepage</em></p>
<p>Go ahead and go to <a target="_blank" href="https://sheets.new">sheets.new</a> to create a brand new Google Sheet. It will also prompt you to sign up if you don't have an account yet. </p>
<p> 💥This is what you'll see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-138.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of a blank spreadsheet</em></p>
<p>😓Some of you may already have begun perspiring because a spreadsheet looks like an unapproachable blank slate reserved for data analysts, financial gurus, and overly ambitious content creators. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/sweat.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of man stressing out</em></p>
<p>💪Fear not. </p>
<p>A spreadsheet, and particularly a Google Sheet, is ripe with possibilities for the average person.</p>
<p>You can use them to enhance productivity after learning only a few basic things. </p>
<p>📊A spreadsheet is a <strong>big grid</strong> made up of <strong>columns labeled with letters</strong> and <strong>rows labeled with numbers</strong>. Each of the rectangles of the grid are called a <strong>cell</strong>, and the active cell is the one with the blue outline. </p>
<p>If you start typing, whatever you type will appear in the active cell.</p>
<p>The cells can contain numbers, words, formulas, dates, pretty much anything...</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-140.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of spreadsheet cell</em></p>
<h2 id="heading-google-sheets-templates">Google Sheets Templates</h2>
<p>Google has supplied us with a respectable amount of templates to get started with. </p>
<p>I will not be covering these in any detail because it's important to get the basics down first. I just want you to be aware of them if you need a starting point <strong>after</strong> you've gotten comfortable with Sheets. </p>
<p>You can look through the template gallery <a target="_blank" href="https://docs.google.com/spreadsheets/u/0/?ftv=1">here</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-142.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of Google Sheets templates</em></p>
<h2 id="heading-menu-and-toolbar-overview">Menu and Toolbar Overview</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/menus.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of Google Sheets menu and toolbar</em></p>
<p>You will likely be familiar with the menu and toolbar setup. As with most modern applications, they are at the top of the page. The menu has many familiar options like File, Edit, View, Insert, and so on. And the toolbar below it consists of mostly icons related to formatting and text options.</p>
<p>The <strong>File</strong> menu has options to share, download, copy, import, rename and other such things related to the whole spreadsheet.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-144.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of file menu</em></p>
<p><strong>Edit</strong> and <strong>View</strong> have familiar options regarding copy/paste and choosing different levels of visibility for your spreadsheet.</p>
<p><strong>Insert</strong> gives us a host of options of things to import into our sheet like charts, pivot tables, checkboxes, emojis, dropdown lists, and many more.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-145.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of insert menu</em></p>
<p><strong>🎨Format</strong> contains many options for formatting our sheet. We can add color, borders, tables styles, and more from here.</p>
<p>The <strong>Data</strong> menu has a lot of spreadsheet specific functions. It contains shortcuts to sort and filter data, to protect different ranges of cells, to group ranges together by naming them, data validation, and advanced items like connecting data sources.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-146.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of the Data menu in Google Sheets</em></p>
<p>Tools and Extensions will be lesser used menus, at least in the beginning. But some really exciting stuff is possible by leveraging the power of <strong>Google Apps Script</strong> through the Extensions menu. This lets us write programs in a language similar to JavaScript all while in a spreadsheet.</p>
<p>But, that's for later – or check out some of my other <a target="_blank" href="https://www.youtube.com/@eamonncottrell">videos</a> and <a target="_blank" href="https://www.freecodecamp.org/news/author/eamonn">articles</a> to get a taste of Apps Script.</p>
<h2 id="heading-basic-data-entry-and-calculations">Basic Data Entry and Calculations</h2>
<p>What is data? According to my Google search, data are "facts and statistics collected together for reference or analysis."</p>
<p>Spreadsheets thrive on data. Yes, think numbers, dates, percentages...things that are easily calculable.</p>
<p>In Google Sheets, we can enter in some data. Say, a list of names, dollar amounts, and dates. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-150.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of some data</em></p>
<p>Now, we have a simple list of data. Because it's small, we can scan it and analyze it ourselves pretty easily. </p>
<ol>
<li>We can see that it's ordered by date</li>
<li>We can see that Paul either has or owes the most</li>
<li>We can see that Sara either has or owes the least</li>
</ol>
<p>But imagine this is a list of thousands of records (each row of an amount, a name, and a date can be referred to as one record).</p>
<p>Suddenly it gets a lot harder to analyze or make sense of the data. </p>
<p>Then add a dozen or a hundred more columns of data for each record. It becomes virtually impossible for a human to draw anything meaningful from the data without the help of a spreadsheet or computer program.</p>
<p>Next, we'll see how some organization and simple spreadsheet operations can help us draw insights from our data.👇</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/easy.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of woman saying this is so easy</em></p>
<h2 id="heading-basic-formatting">Basic Formatting</h2>
<p>Highlight the table. You can do this by clicking and dragging across the whole range of cells. Now, you should have an active <strong>range</strong> instead of an active <strong>cell</strong>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-151.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of Google Sheets table</em></p>
<p>Take a moment and click through some of the formatting options on the toolbar. I've changed the text, the font size, and then made bold the first header row. </p>
<p>I've also highlighted only the dollar amounts, and changed their format to <strong>currency</strong> instead of just a number.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/menus-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of Google Sheets formatting</em></p>
<p>Already, the information is a little more readable. In the next steps we will go further.👇</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/rabbit-hole.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of Alice falling down rabbit hole</em></p>
<h2 id="heading-how-to-create-a-table-in-sheets">How to Create a Table in Sheets</h2>
<p>Alas, we don't (yet) have a swift shortcut like Excel does to make a table. But if we highlight our data again, and select <strong>Format -&gt; Alternating Colors</strong> from the toolbar, we can create table formatting for enhanced readability.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-153.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of Alternating Colors table style in Google Sheets</em></p>
<p>Now, we have banded rows of alternating colors. This becomes very useful in large data sets, but is equally pleasing in our small example. Once satisfied with your color selections, click done.</p>
<p>Now, if we add rows of data to the bottom of our table, Google Sheets is smart enough to know that we probably want to extend the table downward. It will extend the alternating color formatting as we add two more lines:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-154.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of extended Google Sheets table</em></p>
<h2 id="heading-how-to-sort-data-with-a-filter-in-sheets">How to Sort Data with a Filter in Sheets</h2>
<p>Tables are useful because, with some small steps, we can sort and filter data in ways that make it easier to draw conclusions or extract meaning from our data.</p>
<p>Click anywhere in the range of data, and select <strong>Data -&gt; Create a filter</strong> from the Menu bar.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-155.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of creating a filter in Google Sheets</em></p>
<p>Again, Google Sheets knows to create a filter for the entire data set, and you can see two things visually represented: </p>
<ol>
<li>The rows and columns of the data set are now given a highlight color to show that a filter has been applied.</li>
<li>To the right of each header label, there are three horizontal lines that look like an upside-down pyramid. These are the filters.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-156.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of filter on a Google Sheets table</em></p>
<p>From here, we can both sort and/or filter our data. If we sort, for instance, Z -&gt; A, we can display each row from highest to lowest dollar amount.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-157.png" alt="Image" width="600" height="400" loading="lazy">
<em>sorted table</em></p>
<p>If we click the data column's pyramid, we can see that for filtering options, we can either filter by condition or by value.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-158.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of filtering options in Google Sheets</em></p>
<p>Filtering by <strong>values</strong> lets us toggle on or off certain dates. Filtering by <strong>condition</strong> allows for all sorts of options. We can choose dates that are before or after certain dates. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-159.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of filter options in Google Sheets</em></p>
<p>Or we can select "Is between" and then write in a period of dates we want to filter for.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-161.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of filter options in Google Sheets</em></p>
<p>This becomes immensely helpful to narrow down a field of results for analysis. Now we can focus on only the subset of filtered results.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-162.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-intro-to-formulas-and-functions">Intro to Formulas and Functions</h2>
<p>The final piece we'll touch on is the ability to <strong>write formulas</strong> and <strong>use functions</strong>.</p>
<h3 id="heading-formulas-in-google-sheets">Formulas in Google Sheets</h3>
<p>Formulas are instructions we manually type into a cell to manipulate data. If we wanted to add the values in cells A16 and A17, we could write a formula that did this like so: <code>=A16+A17</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-163.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of a formula in Google Sheets</em></p>
<p>We can do basic math very easily like this, but there's an even better way to do this by using functions.</p>
<h3 id="heading-functions-in-google-sheets">Functions in Google Sheets</h3>
<p>Functions are built-in formulas that we use by typing their name. Again, we start out by typing the equals sign, but then we type the name of the function, in this case SUM: <code>=SUM(A16:A17)</code>.</p>
<p>When we begin typing a function, a tooltip will pop up giving us options for the different functions available. You can hit the TAB key to select a function, click one from the list, or complete the spelling of the function and type an open parentheses to select a function.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-165.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of available functions in Google Sheets</em></p>
<p>Once selected, the tooltip will display helper text about that function in case we need an explanation of what it does and/or the variables it needs:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-164.png" alt="Image" width="600" height="400" loading="lazy">
<em>pic of the SUM function in Google Sheets</em></p>
<p>These are straightforward examples of adding numbers, but there are over 400 built-in functions that range greatly in complexity. </p>
<h2 id="heading-whats-next">What's Next?</h2>
<p>As you've probably figured out, this barely scratches the surface of Google Sheets. Once you're comfortable with the basics, it's time to dive deeper and use Sheets to solve some problems of your own.</p>
<p>Check out the templates I've linked above for inspiration, spin up a personal finance tracker, make a workout calendar, track stock prices, build a cost of goods sheet for a small business, build an amortization sheet to see if you can afford a house, track your time with a project management sheet...the possibilities are vast.</p>
<p>🔗Check out my <a target="_blank" href="https://www.youtube.com/@eamonncottrell">YouTube channel</a> and <a target="_blank" href="https://got-sheet.beehiiv.com/subscribe">newsletter</a> for more Sheets content and projects.</p>
<p>🔗Connect with me on <a target="_blank" href="https://www.linkedin.com/in/eamonncottrell/">LinkedIn</a>.</p>
<p>Hope you have a great one!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/bye-gosling.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of Gosling waving bye</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Integrate ChatGPT with Google Sheets Using Google Apps Script ]]>
                </title>
                <description>
                    <![CDATA[ Welcome to this tutorial on how to integrate ChatGPT with Google Spreadsheets using the GPT API and Google Apps Script. We will create two custom formulas, GPT_SUMMARY and GPT_SIMPLIFY. You can use GPT_SUMMARY to summarize a large passage or text int... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-chat-gpt-formulas-in-google-sheets/</link>
                <guid isPermaLink="false">66ba5b03158e6c6a8cb8c7d0</guid>
                
                    <category>
                        <![CDATA[ chatgpt ]]>
                    </category>
                
                    <category>
                        <![CDATA[ google apps script ]]>
                    </category>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Nibesh Khadka ]]>
                </dc:creator>
                <pubDate>Thu, 20 Jul 2023 16:06:35 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/07/GPT-IN-SHeets.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Welcome to this tutorial on how to integrate ChatGPT with Google Spreadsheets using the GPT API and Google Apps Script.</p>
<p>We will create two custom formulas, GPT_SUMMARY and GPT_SIMPLIFY. You can use GPT_SUMMARY to summarize a large passage or text into a few bullet points for easy reading. And you can use GPT_SIMPLIFY to simplify English into easy-to-read English.</p>
<p>We will also create menus with access to functions that perform the same tasks as formulas. We will then discuss the pros and cons of using formulas versus menus. </p>
<p>By the end of this tutorial, you will understand how to use ChatGPT in Google Sheets with Google Apps Script. You will also be able to modify the formulas and menus to meet your own needs, such as creating CVs, social media posts, or cover letters.</p>
<p>You can find the source code for this project in <a target="_blank" href="https://github.com/nibukdk/GPT_Google_Sheets_Integration">this</a> GitHub repo.</p>
<p>If you want to follow along with a video version of this article, here you go:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/DlcJv97TZhE" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h3 id="heading-pre-requisites">Pre-requisites</h3>
<p>This tutorial is not meant for beginners in Apps Script or JavaScript. I will not be explaining every method or classes used in the code. This is also not a tutorial on how to use and optimize ChatGPT – instead we'll focus on how to integrate GPT in Google Sheets.</p>
<h4 id="heading-who-is-this-tutorial-for">Who is this tutorial for?</h4>
<p>This tutorial is for intermediate to advanced users who have a basic understanding of Apps Script and JavaScript. If you are new to either of these, I recommend that you start with a beginner tutorial before attempting this one.</p>
<h2 id="heading-step-1-get-the-chatgpt-api-key">Step 1 – Get the ChatGPT API Key</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1689645559540/943d9a3e-d326-4cd9-ab45-0866898110d2.png" alt="Get ChatGpt API Keys" width="1747" height="992" loading="lazy">
<em>Get ChatGpt API Key</em></p>
<p>First, if you don't already have an account with OpenAI, you'll need to <a target="_blank" href="https://auth0.openai.com/u/signup/identifier?state=hKFo2SBWU2Y5U0ZjYXlDWG5LU0xhdmxhd1pCVW1wQ2ppUUp3eKFur3VuaXZlcnNhbC1sb2dpbqN0aWTZIERpalA1aER5X3hGdEl0TzlRdnlud3FJQ2NlcDduNm4zo2NpZNkgRFJpdnNubTJNdTQyVDNLT3BxZHR3QjNOWXZpSFl6d0Q">create</a> one. Once you have an account, you can create a new API key by going to the API keys section under the User tab. </p>
<p>Click the Create new secret key button and copy the key after it has been created. <em>You will not be able to see this API key again,</em> so be sure to copy it somewhere safe.</p>
<h2 id="heading-step-2-fetch-the-data-from-the-chatgpt-api-with-apps-script">Step 2 – Fetch the Data From the ChatGpt API with Apps Script</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1689558938459/8586ac7a-9b41-41ef-9dcd-c4297436912d.png" alt="Image" width="2227" height="1027" loading="lazy">
<em>Spreadsheet Sample</em></p>
<p>I have named my spreadsheet GPT_Integration with three columns: Passage, Simplified Passage, and Summarized Text.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1689559154810/de6ba3ed-a5af-4a23-ab45-e64bd39a48e6.png" alt="How to Open Apps Script Code Editor From Spreadsheet" width="668" height="482" loading="lazy"></p>
<p>Let's open the app script for this spreadsheet, rename it to GPT_integration, and also rename the existing file to utils.gs. We'll create a function called <code>fetchData</code> here.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> CHAT_GPT_API_KEY = <span class="hljs-string">"paste your API key here"</span>;
<span class="hljs-keyword">const</span> BASE_URL = <span class="hljs-string">"https://api.openai.com/v1/chat/completions"</span>;


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params">systemContent, userContent</span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> headers = {
      <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
      <span class="hljs-string">"Authorization"</span>: <span class="hljs-string">`Bearer <span class="hljs-subst">${CHAT_GPT_API_KEY}</span>`</span>
    };

    <span class="hljs-keyword">const</span> options = {
      headers,
      <span class="hljs-attr">method</span>: <span class="hljs-string">"GET"</span>,
      <span class="hljs-attr">muteHttpExceptions</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">payload</span>: <span class="hljs-built_in">JSON</span>.stringify({
        <span class="hljs-string">"model"</span>: <span class="hljs-string">"gpt-3.5-turbo"</span>,
        <span class="hljs-string">"messages"</span>: [{
          <span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>,
          <span class="hljs-string">"content"</span>: systemContent,
        },
        {
          <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>,
          <span class="hljs-string">"content"</span>: userContent
        },
        ],
        <span class="hljs-string">"temperature"</span>: <span class="hljs-number">0.7</span>
      })
    };

    <span class="hljs-keyword">const</span> response = <span class="hljs-built_in">JSON</span>.parse(UrlFetchApp.fetch(BASE_URL, options));
    <span class="hljs-comment">//console.log(response);</span>
    <span class="hljs-comment">//console.log(response.choices[0].message.content)</span>
    <span class="hljs-keyword">return</span> response.choices[<span class="hljs-number">0</span>].message.content;
  } <span class="hljs-keyword">catch</span> (e) {
    <span class="hljs-built_in">console</span>.log(e)
    SpreadsheetApp.getActiveSpreadsheet().toast(<span class="hljs-string">"Some Error Occured Please check your formula or try again later."</span>);
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Some Error Occured Please check your formula or try again later."</span>;
  }
}
</code></pre>
<p>Here are some key points to notice in the code above:</p>
<ol>
<li>Paste the API key that you created earlier inside the quotes.</li>
<li>We will be using the Chat Completions API. You can find more details about it <a target="_blank" href="https://platform.openai.com/docs/api-reference/chat/create">here</a>.</li>
<li>ChatGPT models have different roles, such as system, user, and assistant.</li>
<li>The systemContent parameter is where you provide roleplay for the GPT system. For example, you could say "You're an expert algebra teacher" or "You're an expert CV writer".</li>
<li>The userContent parameter is where you provide tasks to perform for the model. In our case, we will provide long passages from the spreadsheet to summarize and simplify.</li>
<li>We will be using the <a target="_blank" href="https://platform.openai.com/docs/models/gpt-3-5">GPT 3.5 turbo model</a>.</li>
<li>We are muting HTTPExceptions so that we can use our own error message in the catch block.</li>
<li>The error string is useful when we face errors such as <a target="_blank" href="https://platform.openai.com/docs/guides/rate-limits/what-are-the-rate-limits-for-our-api">Rate Limit Exceed</a>.</li>
</ol>
<p>We're returning the content from the response object of GPT that'll be later on handled by our formulas.</p>
<p>The response object from ChatGPT has following structure:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"id"</span>: <span class="hljs-string">"chatcmpl-123"</span>,
  <span class="hljs-attr">"object"</span>: <span class="hljs-string">"chat.completion"</span>,
  <span class="hljs-attr">"created"</span>: <span class="hljs-number">1677652288</span>,
  <span class="hljs-attr">"choices"</span>: [{
    <span class="hljs-attr">"index"</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">"message"</span>: {
      <span class="hljs-attr">"role"</span>: <span class="hljs-string">"assistant"</span>,
      <span class="hljs-attr">"content"</span>: <span class="hljs-string">"\n\nHello there, how may I assist you today?"</span>,
    },
    <span class="hljs-attr">"finish_reason"</span>: <span class="hljs-string">"stop"</span>
  }],
  <span class="hljs-attr">"usage"</span>: {
    <span class="hljs-attr">"prompt_tokens"</span>: <span class="hljs-number">9</span>,
    <span class="hljs-attr">"completion_tokens"</span>: <span class="hljs-number">12</span>,
    <span class="hljs-attr">"total_tokens"</span>: <span class="hljs-number">21</span>
  }
}
</code></pre>
<p>Read more on how to use URLFetchApp from <a target="_blank" href="https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app">here</a>.</p>
<h2 id="heading-step-3-integrate-chatgpt-as-a-sheets-formula">Step 3 – Integrate ChatGpt as a Sheets Formula</h2>
<h3 id="heading-gpt-simplify-formula">GPT SIMPLIFY Formula</h3>
<p>Again, for the custom formula, we'll create a new file named formula and then we will create a function named GPT_SIMPLIFY.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * Simplifies the given paragraph in layman's term.
 * <span class="hljs-doctag">@param <span class="hljs-type">{String}</span> </span>input The value to simplify.
 * <span class="hljs-doctag">@return </span>Simplified Text.
 * <span class="hljs-doctag">@customfunction</span>
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">GPT_SIMPLIFY</span>(<span class="hljs-params">input</span>) </span>{
  <span class="hljs-built_in">console</span>.log(input)
  <span class="hljs-keyword">const</span> systemContent = <span class="hljs-string">"Simplify the given text in layman's term. Remember reader is not an expert in english."</span>;
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>.isArray(input) ?
    input.flat().map(<span class="hljs-function"><span class="hljs-params">text</span> =&gt;</span> fetchData(systemContent, text)) :
    fetchData(systemContent, input);

}
</code></pre>
<ol>
<li>The <code>GPT_SIMPLIFY</code> formula simplifies whatever text is provided as input. The input to this function is data that is coming from the spreadsheet. When you select a range, a cell, or multiple cells, the data in the range will be automatically provided by the spreadsheet to this formula.</li>
<li>The <code>systemContent</code> is defined to be passed as the first parameter to the <code>fetchData(systemContent,userContent)</code> function. </li>
<li>We are checking if the input is an Array because the data passed to this function can either be a nested array or just a string if we select multiple cells or single cell, respectively, in the spreadsheet.</li>
</ol>
<p>You can read more on custom functions on this <a target="_blank" href="https://developers.google.com/apps-script/guides/sheets/functions">page</a>.</p>
<p>Now go ahead and apply this formula in your spreadsheet. I copied some text from a book I'm reading in the first column and applied the formula in the second column named "Simplify Passage", like this <code>=GPT_SIMPLIFY(A2)</code> for the second cell.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/gpt_simplify_formula.png" alt="Image" width="600" height="400" loading="lazy">
_Appilcation of GPT<em>SIMPLIFY Formula</em></p>
<p>Note: Make sure to refresh the spreadsheet before you apply the formula to sync with the latest changes in the script.</p>
<h3 id="heading-gpt-summarize">GPT SUMMARIZE</h3>
<p>To summarize the formula we'll just copy the simplify function and some other things, as you can see in the code below.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * Summarzies the given paragraph. It provides from 3-5 bullet points
 *
 * <span class="hljs-doctag">@param <span class="hljs-type">{String}</span> </span>input The value to summarize.
 * <span class="hljs-doctag">@return </span>summarize Text.
 * <span class="hljs-doctag">@customfunction</span>
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">GPT_SUMMARY</span>(<span class="hljs-params">input</span>) </span>{
  <span class="hljs-built_in">console</span>.log(input)
  <span class="hljs-keyword">const</span> systemContent = <span class="hljs-string">"Summarize the given text. Provide atleast 3 and atmost 5 bullet points."</span>;
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>.isArray(input) ?
    input.flat().map(<span class="hljs-function"><span class="hljs-params">text</span> =&gt;</span> fetchData(systemContent, text)) :
    fetchData(systemContent, input);

}
</code></pre>
<p>The main thing to notice here is the different system content.</p>
<p>Note: Since this is not a tutorial on how to use ChatGpt optimally, I provided instructions as the system content instead of role-play, and then just provided data in the user content. You can improvise this by providing roles in system content, and tasks as well as data as two different user roles in our <code>FetchData()</code> function.</p>
<h3 id="heading-gpt-rate-limit-error">GPT Rate Limit Error</h3>
<p>For free users, the rate limit to use the API is <strong>3/minute</strong>. As such, when you apply these formulas in more than three cells you'll encounter the error. Luckily the execution won't stop because we're returning an error string from fetch data which will be saved into those cells.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1689574131023/70e326ac-33bd-4d75-96db-208fc27b5859.png" alt="GPT Rate Limit Error" width="2178" height="321" loading="lazy">
<em>API rate limit error</em></p>
<h3 id="heading-auto-refresh-and-error">Auto Refresh and Error</h3>
<p>Moreover, the auto-refresh feature of the formula can force the re-application of the formula on cells that already have satisfying values whenever source cells are updated, in our case cells in column "A".</p>
<p>When we add a rate limit on top of auto-refresh it can cause a conundrum. You can technically make changes in custom functions to accommodate such circumstances but, I like to keep formulas light and efficient. So, I recommend we instead create custom menus and apply these functions manually.</p>
<h2 id="heading-step-4-integrate-gpt-chat-api-in-spreadsheet-menu-functions">Step 4 – Integrate GPT Chat API in Spreadsheet Menu Functions</h2>
<h3 id="heading-gpt-simplify-menu">GPT Simplify Menu</h3>
<p>First, let's create another file named <code>menu</code>. Then we'll create the <code>gptSimplifyMenu</code> function which will be an alternative to the GPT_SIMPLIFY formula.</p>
<pre><code class="lang-javascript">
<span class="hljs-comment">/**
 * Simplifies the given paragraph in layman's term.
 * <span class="hljs-doctag">@customfunction</span>
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">gptSimplifyMenu</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// get sheets and data</span>
    <span class="hljs-keyword">const</span> ss = SpreadsheetApp.getActiveSheet();
    <span class="hljs-keyword">const</span> data = ss.getDataRange().getValues();
    <span class="hljs-keyword">const</span> lastRow = data.length;
    <span class="hljs-keyword">const</span> lastCol = data[<span class="hljs-number">0</span>].length;

    <span class="hljs-comment">// define gpt's role play</span>
    <span class="hljs-keyword">const</span> systemContent = <span class="hljs-string">"Simplify the given text in layman's term. Remember reader is not an expert in english."</span>;


    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">1</span>; i &lt; data.length; i++) {
      <span class="hljs-comment">// only simplify if not already simplified or error occured previously</span>
      <span class="hljs-keyword">if</span> (data[i][<span class="hljs-number">1</span>] === <span class="hljs-string">""</span> || data[i][<span class="hljs-number">1</span>] === <span class="hljs-string">"Some Error Occured Please check your formula or try again later."</span>) {
        data[i][<span class="hljs-number">1</span>] = fetchData(systemContent, data[i][<span class="hljs-number">0</span>]);
        <span class="hljs-built_in">console</span>.log(data[i][<span class="hljs-number">1</span>]);

      }
    }

    ss.getRange(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, lastRow, lastCol).setValues(data);
  } <span class="hljs-keyword">catch</span> (e) {
    <span class="hljs-built_in">console</span>.log(e)
    SpreadsheetApp.getActiveSpreadsheet().toast(<span class="hljs-string">"Some Error Occured Please check your formula or try again later."</span>);

  }
}
</code></pre>
<p>Key points that are different to understand in this code are:</p>
<ol>
<li>We're hardcoding the data sources, as such data[i][1], which refers to the second column (that is "Simplified Passage") as shown in the spreadsheet image above. This means that if you're using some other columns to save data from ChatGPT to, then you'll have to make changes according to it.</li>
<li>We only fetch data when the target cell is empty or contains an error message. This helps to avoid unnecessary API calls.</li>
</ol>
<h3 id="heading-add-a-custom-function-as-a-spreadsheet-menu">Add a Custom Function as a Spreadsheet Menu</h3>
<p>The function is ready to be tested, but it still will not appear in the spreadsheet. To do so, we'll need to provide the following instructions.</p>
<pre><code class="lang-javascript">
<span class="hljs-comment">/**
 * Menu creates menu UI in spreadsheet.
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createCustomMenu</span>(<span class="hljs-params"></span>) </span>{
   <span class="hljs-comment">// define menu ui </span>
  <span class="hljs-keyword">let</span> menu = SpreadsheetApp.getUi().createMenu(<span class="hljs-string">"GPT Functions"</span>);
   <span class="hljs-comment">// add function to the menu</span>
   menu.addItem(<span class="hljs-string">"GPT SIMPLIFY"</span>, <span class="hljs-string">"gptSimplifyMenu"</span>);
   <span class="hljs-comment">// add menu to the spreadsheet ui</span>
  menu.addToUi();
}

<span class="hljs-comment">/**
 * OnOpen trigger that creates menu
 * <span class="hljs-doctag">@param <span class="hljs-type">{Dictionary}</span> <span class="hljs-variable">e</span></span>
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">onOpen</span>(<span class="hljs-params">e</span>) </span>{
  createCustomMenu();
}
</code></pre>
<p>In <code>createCustomMenu()</code>:</p>
<ol>
<li>We define menu with <a target="_blank" href="https://developers.google.com/apps-script/reference/base/ui#createmenucaption"><code>SpreadsheetApp.getUi().createMenu("GPT Functions")</code></a> as GPT Functions the title appearing in the spreadsheet tab.</li>
<li>We add a function to the menu with the <code>menu.addItem("GPT SIMPLIFY", "gptSimplifyMenu")</code>, where the first parameter is the title for display and the second is the function to call when pressed.</li>
<li>Add the menu to the UI with <code>menu.addToUi()</code>.</li>
</ol>
<p>The <a target="_blank" href="https://developers.google.com/apps-script/guides/triggers#onopene">onOpen</a> trigger runs automatically whenever the document the script is attached to reloads and as such will add a menu to the spreadsheet as shown in the image below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1689573996102/660acf86-567e-4261-96db-2a8ed1c2182c.png" alt="GPT Function Menu" width="1009" height="236" loading="lazy"></p>
<p>Go ahead and try the formula – it'll only be applied if the cell is either empty or prefilled with an error message.</p>
<h3 id="heading-gpt-summarize-menu">GPT Summarize Menu</h3>
<p>We'll make some minor changes after copying the simplify function as shown below:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * Summarzies the given paragraph. It provides from 3-5 bullet points
 * <span class="hljs-doctag">@customfunction</span>
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">gptSummaryMenu</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// get sheets and data</span>
    <span class="hljs-keyword">const</span> ss = SpreadsheetApp.getActiveSheet();
    <span class="hljs-keyword">const</span> data = ss.getDataRange().getValues();
    <span class="hljs-keyword">const</span> lastRow = data.length;
    <span class="hljs-keyword">const</span> lastCol = data[<span class="hljs-number">0</span>].length;

    <span class="hljs-comment">// define gpt's role play</span>
    <span class="hljs-keyword">const</span> systemContent = <span class="hljs-string">"Summarize the given text. Provide atleast 3 and atmost 5 bullet points."</span>;


    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; data.length; i++) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Inside gptSummaryMenu() for loop`</span>)

      <span class="hljs-keyword">if</span> (i == <span class="hljs-number">0</span>) <span class="hljs-keyword">continue</span>;
      <span class="hljs-comment">// only summarize if not already summarized or error occured previously</span>
      <span class="hljs-keyword">if</span> (data[i][<span class="hljs-number">2</span>] === <span class="hljs-string">""</span> || data[i][<span class="hljs-number">2</span>] === <span class="hljs-string">"Some Error Occured Please check your formula or try again later."</span>) {
        data[i][<span class="hljs-number">2</span>] = fetchData(systemContent, data[i][<span class="hljs-number">0</span>]);
        <span class="hljs-built_in">console</span>.log(data[i][<span class="hljs-number">2</span>]);
      }
    }

    ss.getRange(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, lastRow, lastCol).setValues(data);
  } <span class="hljs-keyword">catch</span> (e) {
    <span class="hljs-built_in">console</span>.log(e)
    SpreadsheetApp.getActiveSpreadsheet().toast(<span class="hljs-string">"Some Error Occured Please check your formula or try again later."</span>);
  }
}
</code></pre>
<ol>
<li>The system role has been changed to address summary instruction.</li>
<li>The target column to save data is now the third column.</li>
<li>The doc string has been adjusted as well.</li>
</ol>
<p>As for adding this function to the menu I'll leave it to you.</p>
<h2 id="heading-tips-to-modify-the-code">Tips to Modify the Code</h2>
<p>All you need to make your own formula like =GPT_COVER_LETTER_CREATOR() are the following modifications:</p>
<h3 id="heading-to-fetchdata">To FetchData</h3>
<p>You can change System Content Description should to address your needs, like "You write an expert cover letter for software developers".</p>
<p>Add one more instruction in the messages array:</p>
<pre><code class="lang-json"><span class="hljs-comment">// from this </span>
[{
          <span class="hljs-attr">"role"</span>: <span class="hljs-string">"system"</span>,
          <span class="hljs-attr">"content"</span>: systemContent,
        },
        {
          <span class="hljs-attr">"role"</span>: <span class="hljs-string">"user"</span>,
          <span class="hljs-attr">"content"</span>: userContent
        },
        ], 

<span class="hljs-comment">// to </span>
[{
          <span class="hljs-attr">"role"</span>: <span class="hljs-string">"system"</span>,
          <span class="hljs-attr">"content"</span>: <span class="hljs-string">"You write an expert cover letter for software developers"</span>,
        },
        {
          <span class="hljs-attr">"role"</span>: <span class="hljs-string">"user"</span>,
          <span class="hljs-attr">"content"</span>: <span class="hljs-string">"Write me a cover letter for this given job advertisement"</span>
        },
        {
          <span class="hljs-attr">"role"</span>: <span class="hljs-string">"user"</span>,
          <span class="hljs-attr">"content"</span>: userContent <span class="hljs-comment">// this is job ad from spreadsheet</span>
        },
        ],
</code></pre>
<p>You can also add another list item to include your skills and experiences.</p>
<h3 id="heading-other-functions">Other Functions</h3>
<p>Just make sure that your source cell/columns and target cell/columns are accurately indexed (for instance, if you're not using the first column as the source cell and the second to save the data).</p>
<h2 id="heading-summary">Summary</h2>
<p>In this tutorial, you learned how to use Google Apps Script to fetch ChatGPT responses from the API and save them into spreadsheets using custom formulas and custom menus.</p>
<p>We started by creating a new Google Apps Script project and adding the ChatGPT API. Then, we wrote a script that would fetch a ChatGPT response for a given prompt. We saved the response using a custom formula into a spreadsheet cell.</p>
<p>We also created a custom menu item that would allow us to fetch a ChatGPT response from any cell in the spreadsheet. This menu item would open a button to fetch the response.</p>
<p>The final step was to share the spreadsheet with others so that they could use the custom formulas and menus to fetch ChatGPT responses.</p>
<p>I hope you enjoyed this article and found it helpful. If you have any questions, just let me know.</p>
<p>I am <strong>Nibesh Khadka,</strong> Freelancer specializing in automating Google products with Apps Script. Contact me if you need my services at me@nibeshkhadka.com.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ AI in Google Sheets – How to Use GPT Copilot ]]>
                </title>
                <description>
                    <![CDATA[ It seems to be the year of AI. And my favorite tool, Google Sheets, is not to be left out of the fun. 🎉 Coefficient produced a Google sheets extension with the ability to use OpenAI's GPT models from within a spreadsheet. It’s called GPT Copilot an... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/ai-in-google-sheets/</link>
                <guid isPermaLink="false">66b8ddcc0cedc1f2a4f70674</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Artificial Intelligence ]]>
                    </category>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Mon, 12 Jun 2023 22:10:01 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/06/ai-in-google-sheets-thumb.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>It seems to be the year of AI. And my favorite tool, Google Sheets, is not to be left out of the fun. 🎉</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/giphy.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://coefficient.io/gpt-google-sheets">Coefficient</a> produced a Google sheets extension with the ability to use OpenAI's GPT models from within a spreadsheet. It’s called GPT Copilot and it’s available to try for free. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/Screenshot-2023-06-09-at-8.00.44-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of Coefficient's GPT in Sheets page</em></p>
<p>I have been putting off looking into this tool for quite some time, though I've been following Coefficient's Google Sheets work for a while now.</p>
<p>To be honest, I'd gotten a little tired of all the AI talk and was wary of yet another effort in that realm. Do I really need to use AI in spreadsheets? </p>
<p>🤷Yes and no.</p>
<h2 id="heading-video-example">Video Example</h2>
<p>I made a quick video walking through a handful of the GPTx functions, and I'll detail all of them in the article below. If you have a sec, check out the 2.5 min video and give it a 👍.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/HaKYyPLaOFA" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>The extension is pretty cool.</p>
<p>AI is not some thing that is going to do all of my work for me. But it is a pretty powerful tool with which I can do work faster, more efficiently, and in some cases get some unique inspiration from.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/potential.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of ted lasso saying, smells like potential</em></p>
<h2 id="heading-gpt-copilot-functions">GPT Copilot Functions</h2>
<p>In the GPT Copilot extension on Google Sheets, we are given a list of several built-in <code>GPTX</code> functions we can now use directly in the sheet itself. </p>
<p><a target="_blank" href="https://docs.google.com/spreadsheets/d/1CaLdC22IS_9K42ycwkyYlnsCSGsEpyJtedPWXxn5poI/edit#rangeid=903106705">Here</a> is a document with all the functions listed out, and we'll go through each below.</p>
<p>And <a target="_blank" href="https://docs.google.com/spreadsheets/d/10suhdcRdi5NI_PCGO0VK1TXiLIGdy44T8R3zL9938So/edit?usp=sharing">here's the spreadsheet</a> I used for all my samples and the video. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/Screenshot-2023-06-09-at-8.12.07-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The first function, <code>=GPTX(prompt)</code> simply lets us generate text using Open AI's GPT model.</p>
<p>I used this to generate a subject line for an email below. This generic <code>GPTX</code> function can be used to query ChatAI's model for anything you can think of: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-113.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of GPTX() function</em></p>
<p>Then we get <code>**=GPTX_LIST(prompt)**</code> which lets us generate a list of values in the same way. </p>
<p>This is similar to the first example, but the list of items will appear in separate cells so it's handy if you want...say, the top 10 video games by sales in Korea:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-114.png" alt="Image" width="600" height="400" loading="lazy">
_Screenshot of GPTX<em>LIST() function</em></p>
<p><code>**=GPTX_EDIT(text,[task])**</code> was useful as I went through and created email body messages based on a prompt that I fed into the function. So it lets us perform a task or transformation on an input text.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/Screenshot-2023-06-09-at-8.14.09-PM.png" alt="Image" width="600" height="400" loading="lazy">
_screenshot of GPTX<em>EDIT function</em></p>
<p><code>**GPTX_MAP(search_keys, inputs)**</code> performs a fuzzy search, given a list of search keys in the list of input values, and then outputs the most similar search for each input value.</p>
<p>If we have a list of games and platform companies, it can map the company values to the correct game:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-124.png" alt="Image" width="600" height="400" loading="lazy">
_Screenshot of GPTX<em>MAP()</em></p>
<p><code>**GPTX_FILL(text, [task])**</code> fills in missing information in the table based on example rows.</p>
<p>This will let you feed it some example data and have GPTX fill in the rest:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-115.png" alt="Image" width="600" height="400" loading="lazy">
_Screenshot of GPTX<em>FILL</em></p>
<p><code>**GPTX_TABLE(prompt, [header_row])**</code> generates a table of values. This one was particularly cool because you can give it a real query to get data from, or have it fill out a table with dummy data.</p>
<p>Here we can pull in some population info on the top 5 cities in Tennessee: 😀</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-116.png" alt="Image" width="600" height="400" loading="lazy">
_Screenshot of GPTX<em>TABLE()</em></p>
<p><code>**GPTX_FORMAT(text, language)**</code> converts input values into the specified format. </p>
<p><code>**GPTX_TAG(text, tags)**</code> does what it sounds like: it applies one or more tags matching a piece text.</p>
<p>If you have a list of movies, and a list of genres, you can tag them here. Interestingly:</p>
<ol>
<li>GPT doesn't seem to have a sense of humor as it didn't classify Waterworld as a flop.</li>
<li>It also won't blindly fill in genres that are missing from the list (Goldeneye and Seven)</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/flop.png" alt="Image" width="600" height="400" loading="lazy">
_Screenshot of GPTX<em>TAG()</em></p>
<p>Another cautionary tale, though...when I added crime to see if it would fill in Seven's blank, it actually came back with different answers on some of the others...and left off Casper and Jumanji this time. So, while nothing is really tagged incorrectly, it does have varying results. </p>
<p>In this case, it does behave like a human, in a way. You'll get different people answering this type of tagging question in different ways too. 🤷‍♂️</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><code>**GPTX_CLASSIFY(text, labels)**</code>, in the same way, classifies text given a set of labels or categories.</p>
<p><code>**GPTX_EXTRACT(text, info_to_extract)**</code> extracts the desired information from the input text. So if you have an address in a cell, it can extract the city name from the address.</p>
<blockquote>
<p>Caution though; I encountered several instances while writing these GPTX functions where I got #ERROR!s and had to refresh the page, close it and reopen, or simply wait a while...</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-118.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><code>**GPTX_SUMMARIZE(text, language)**</code> summarizes the input text according to the given format.</p>
<p>I tried to be clever here. I pasted the first chapter of The Great Gatsby into a cell. Pretty quickly got a "too large" error 😂)</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-119.png" alt="Image" width="600" height="400" loading="lazy">
_screenshot of GPTX<em>Summarize error</em></p>
<p>But! Reducing down to the first 726 words was sufficient to have it actually summarize the beginning of this awesome novel:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-121.png" alt="Image" width="600" height="400" loading="lazy">
_Screenshot of GPTX<em>SUMMARIZE() summarizing the start of The Great Gatsby</em></p>
<p><code>**GPTX_TRANSLATE(text, language)**</code> translates the input text into the specified language.</p>
<p>This one's straightfoward and not incredibly useful for my spreadsheets...but nonetheless, it's pretty neat:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-122.png" alt="Image" width="600" height="400" loading="lazy">
_Screenshot of GPTX<em>TRANSLATE()</em></p>
<p><code>**GPTX_CONVERT(text, format)**</code> converts the input text into the specified structured format.</p>
<p><code>**GPTX_CODE(task, language)**</code>generates code in a specified language, which performs the specified task. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/Screenshot-2023-06-09-at-8.21.54-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><code>GPTX_CODE()</code> was really neat. I also see the most chances for problems here because novices will be tempted to blindly use code not knowing how or if it works.</p>
<p>This seems most beneficial as a helper for when I know how the code should work, but can prompt for the basic skeleton instead of needing to search for methods on my own.</p>
<h2 id="heading-limits-to-gpt-copilot">Limits to GPT Copilot</h2>
<p>Are there limits to the number of prompts you can feed these functions? Yes. Of course there are. 😆</p>
<p>To stay free, you get 10,000 executions. Monthly plans start at 100,000 executions per month.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/Screenshot-2023-06-09-at-8.33.46-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot from the Coefficient GPT CopilotFAQ</em></p>
<h2 id="heading-what-i-think">What I Think</h2>
<p>I walk through some real basic stuff that I could have generated on my own in the <a target="_blank" href="https://youtu.be/HaKYyPLaOFA">example video</a> that I encourage you to watch. But I do see the potential for this to be a very helpful tool as the ecosystem matures.</p>
<p>Insofar as dummy data is concerned, it is really helpful to just generate stuff in a spreadsheet quickly.</p>
<p>And it works great to fill in the blanks where you previously might do a little bit more manual labor, extracting values, formatting things, classifying things, and so on.</p>
<p>In addition to these built-in functions, the Coefficient add-on also contains a pivot builder, a formula builder, and a chart builder tool.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/Screenshot-2023-06-09-at-8.25.26-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of Coefficient's extension</em></p>
<p>These allow you to feed a prompt into the extension based on the data in your spreadsheet, and it will generate either a pivot table, a formula, or a chart.</p>
<p>These are kind of crutches for doing some pretty basic operations in Google Sheets. But they do have an interesting utility and are pretty reliable when you give well-written prompts to them.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>🤔 AI tools can be a big time sink. It's pretty easy to spend more time getting mediocre results from them than it would have taken to do things manually.</p>
<p>But, that's part of the learning curve for any toolkit. Upfront investments can certainly pay off in the long run. I'll keep using these tools to hopefully make better spreadsheets more efficiently.</p>
<p>❓What do you think? Is this another example of over-engineering simple things? Or is it the next big thing in Google Sheets?</p>
<p>Come join the conversation on my YouTube channel: <a target="_blank" href="https://www.youtube.com/@eamonncottrell?sub_confirmation=1">https://www.youtube.com/@eamonncottrell?sub_confirmation=1</a></p>
<p>Or my LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/eamonncottrell/">https://www.linkedin.com/in/eamonncottrell/</a></p>
<p>Have a great one! 👋</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Google Sheets – How to Make a Dynamic Search Bar ]]>
                </title>
                <description>
                    <![CDATA[ This tutorial is for when CTRL + F is not enough. 🔥 I bet I've used the CTRL + F shortcut more than any other keyboard shortcut in my life. CTRL + Z probably comes close, but I use CTRL + F to find things... 💥ALL 💥 💥💥THE 💥💥 💥💥💥TIME ]]>
                </description>
                <link>https://www.freecodecamp.org/news/dynamic-search-bar-google-sheets/</link>
                <guid isPermaLink="false">66b8dddbfedc3fd92fddb767</guid>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ search ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Fri, 02 Jun 2023 13:31:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/06/Google-Sheets-Dynamic-Search-Bar-with-profile.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This tutorial is for when CTRL + F is not enough. 🔥</p>
<p>I bet I've used the CTRL + F shortcut more than any other keyboard shortcut in my life. CTRL + Z probably comes close, but I use CTRL + F to find things...</p>
<p>💥<strong>ALL 💥</strong></p>
<p>💥💥<strong>THE</strong> 💥💥</p>
<p>💥💥💥<strong>TIME</strong> 💥💥💥</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/more2.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of man saying we need more</em></p>
<p>And yes, it'll work just fine in a Google Sheet to find information.</p>
<p>But sometimes I want to display a range of results based on a word I'm searching for. To do that, we'll create a dynamic search bar in our Google Sheet.</p>
<p>You can also follow along in this walkthrough video:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/5xgwvokDhT0" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-the-search-bar">The Search Bar</h2>
<p>Our search bar is nothing more than a cell or range of cells. In the example below, it starts in J2.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/google-sheets-search-bar.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of a search bar on Google Sheets</em></p>
<p>By adding a <code>=QUERY()</code> function in J5 we can look at whatever is typed into <code>J2</code> (the red circle) and display the search results below it (the blue rectangle).</p>
<p>In my example, I'm searching through a bunch of personal finance transactions (with randomized amounts😀) that are in columns <code>A:F</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/google-sheets-finance-data.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of finance data on Google Sheets</em></p>
<h2 id="heading-the-query-function">The Query Function</h2>
<p>The <code>=QUERY()</code> function looks in the Transactions range (which is that <code>A3:F</code> range where all the transactions live).</p>
<p>And it grabs all the info in either column B or column D that <code>CONTAINS</code> what we type in <code>J2</code>.</p>
<p>So it searches through all our transaction descriptions in column B and categories in column D for whatever we type in <code>J2</code>. The <code>LOWER</code> command turns the info in B and D into lowercase. This makes it easier to search because the <code>CONTAINS</code> command is case-sensitive.</p>
<pre><code class="lang-javascript">=QUERY(Transactions, 
       <span class="hljs-string">"SELECT A,B,C,D,E WHERE LOWER(B) CONTAINS '"</span>&amp;J2&amp;<span class="hljs-string">"' OR LOWER(D) CONTAINS '"</span>&amp;J2&amp;<span class="hljs-string">"'"</span>)
</code></pre>
<ul>
<li>the only caveat is that if you type in uppercase in the search bar, it won't work properly.</li>
</ul>
<h2 id="heading-the-filter-function">The Filter Function</h2>
<p>By using the <code>=FILTER()</code> function in combination with the <code>=SEARCH()</code> function, we can do the same thing in a little bit shorter formula and without having to worry about case sensitivity.</p>
<pre><code class="lang-xls">=<span class="hljs-built_in">IF</span>(<span class="hljs-built_in">ISBLANK</span>(<span class="hljs-symbol">J2</span>),<span class="hljs-string">""</span>,FILTER(Transactions,<span class="hljs-built_in">SEARCH</span>(<span class="hljs-symbol">J2</span>,<span class="hljs-symbol">B3</span>:<span class="hljs-symbol">B225</span>)))
</code></pre>
<p>The tradeoff here is that when we want to add multiple conditions like we did in the <code>=QUERY()</code> statement, it breaks down. Both <code>=FIND()</code> and <code>=SEARCH()</code> did not work properly when trying to use them more than once inside the <code>=FILTER()</code>.</p>
<p>I was able to find a work around by using the plus operator and constructing the formula in this way:</p>
<pre><code class="lang-xls">=<span class="hljs-built_in">IF</span>(<span class="hljs-built_in">ISBLANK</span>(<span class="hljs-symbol">J2</span>),<span class="hljs-string">""</span>,FILTER(Transactions,(<span class="hljs-symbol">B3</span>:<span class="hljs-symbol">B225</span>=<span class="hljs-symbol">J2</span>)+(<span class="hljs-symbol">D3</span>:<span class="hljs-symbol">D225</span>=<span class="hljs-symbol">J2</span>)))
</code></pre>
<p>Unfortunately when you filter in this way, partial matches are not included in the search results. </p>
<p>In the case of Query, partial answers are always returned. </p>
<p>So, when we enter "hom" all the lines with "home" in it would be returned. When using multiple conditions with filter, nothing would return unless you entered the whole word "home".</p>
<h2 id="heading-what-about-xlookup">What About XLOOKUP?</h2>
<p>The issue with XLOOKUP is twofold. One, it doesn't handle partial matches well unless you add wildcard characters:</p>
<pre><code class="lang-xls">=XLOOKUP(<span class="hljs-string">"*"</span>&amp;<span class="hljs-symbol">J2</span>&amp;<span class="hljs-string">"*"</span>,<span class="hljs-symbol">B3</span>:<span class="hljs-symbol">B225</span>,<span class="hljs-symbol">A3</span>:<span class="hljs-symbol">F225</span>,,<span class="hljs-number">2</span>)
</code></pre>
<p>This increases complexity but still works. </p>
<p>The more important difference is that it will only return one result so it's not going to work at all for us for this use case.</p>
<h2 id="heading-the-winner-is-query">The Winner is Query</h2>
<p>Query takes the prize simply because it doesn't need further manipulation to add multiple conditions, and it will return all the values that meet our search criteria.</p>
<p>It may take you a minute to wrap your head around the syntax, but it's just as powerful and more versatile than Filter in the long haul.</p>
<p>The only thing to make sure to remember is case sensitivity. If you're using the <code>LOWER</code> command in your query, don't use any uppercase search letters. </p>
<h2 id="heading-make-it-neat">Make it Neat</h2>
<p>In the full formula, I've added an <code>=IF()</code> function at the start to handle the blank search bar. We want to return nothing in that case:</p>
<pre><code class="lang-xls">=<span class="hljs-built_in">IF</span>(<span class="hljs-built_in">ISBLANK</span>(<span class="hljs-symbol">J2</span>),<span class="hljs-string">""</span>, QUERY(Transactions <span class="hljs-string">"SELECT A,B,C,D,E WHERE LOWER(B) CONTAINS '"</span>&amp;<span class="hljs-symbol">J2</span>&amp;<span class="hljs-string">"' OR LOWER(D) CONTAINS '"</span>&amp;<span class="hljs-symbol">J2</span>&amp;<span class="hljs-string">"'"</span>)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-30.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of a blank search bar in Google Sheets</em></p>
<h2 id="heading-follow-along">Follow Along</h2>
<p>Come <a target="_blank" href="https://www.youtube.com/@eamonncottrell?sub_confirmation=1">follow me over on YouTube</a> as I make tutorials each week.</p>
<p><a target="_blank" href="https://got-sheet.beehiiv.com/subscribe">Sign up here</a> to get my newsletter in your email each week.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/Beehiivp.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Eamonn's Sheets | Coding | Education logo</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create Data Validation Rules in Excel ]]>
                </title>
                <description>
                    <![CDATA[ By Faith Oyama Data validation is a feature in Excel used in restricting data entry in specific cells. It can also prompt the user to enter valid data into the cells based on the rules and restrictions provided by the creator of the Excel worksheet. ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-data-validation-rules-excel/</link>
                <guid isPermaLink="false">66d45edd4a7504b7409c33d5</guid>
                
                    <category>
                        <![CDATA[ data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ excel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 26 May 2023 00:07:47 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/pexels-pixabay-262438.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Faith Oyama</p>
<p>Data validation is a feature in Excel used in restricting data entry in specific cells. It can also prompt the user to enter valid data into the cells based on the rules and restrictions provided by the creator of the Excel worksheet. </p>
<p>When setting up a workbook, you might want to make sure users input a specific type of data. For example, you might want to allow only dates, numbers, or letters in a specific range to be imputed in a cell. This is crucial if you want to eliminate mistakes as much as possible in your data.</p>
<h2 id="heading-types-of-data-validation-rules-in-excel">Types of Data Validation Rules in Excel</h2>
<p>Here are a few data validation rules you can set up in Excel:</p>
<ul>
<li>Only allow text or numeric values in a cell.</li>
<li>Only allow numbers within a specific range.</li>
<li>Display a warning message when a user inputs the wrong data.</li>
<li>Only allow dates and times outside a given range.</li>
<li>Validation rule based on criteria from another cell.</li>
</ul>
<h2 id="heading-steps-to-create-data-validation-rules-in-excel">Steps to Create Data Validation Rules in Excel.</h2>
<p>To create a data validation rule in Excel, do the following:</p>
<p>First, select the row, column, or specific cell you want to apply a data validation rule to.</p>
<p>Then open the data pane and click on the data validation. Alternatively, you can go directly to the data validation dialogue box by pressing the following keys on your keyboard separately. ALT &gt; D &gt; L. Do not hold the keys together, press the keys separately and you will be taken to the dialogue box as well.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/data-menu.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Create the data validation based on what data you want to be supplied in the cell or row.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/data-validation.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can supply the following validation criteria:</p>
<p><strong>Allow</strong>: Make a rule based on the type of data you want to allow. You can choose one from the drop-down menu. You can uncheck the “Ignore blank” button if you do not want blank spaces.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/select-whole-number.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>Data</strong>: From the drop-down menu you can choose the criteria and also input the minimum and maximum values you want the user to input. </p>
<p>With the validation criteria set, click OK to close the window or click on the Input Message or Error Alert tab to give the user more information on the data validation rule.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/select-between.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>Input message</strong>: While this is optional, you can input a message to be displayed when a user clicks on a cell that has a data validation rule defined on it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/input-message.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next, give your input message a title, and under the input message, make sure the message you provide is clear to the user. Click on OK to close the dialogue box or navigate to the Error Alert tab.</p>
<p>Then display an error message. This is optional, but it is good practice to display an error message to users when they enter data that is outside the validation rule you set.</p>
<p>There are three types of error alerts:</p>
<ol>
<li><strong>Stop:</strong> This is the default and is very strict, as it stops users from entering  invalid data. You can only click on “Retry” or “Cancel”</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/enter-a-valid-number-popup.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ol start="2">
<li><strong>Warning:</strong> This will only warn the user but is not as strict as the stop warning. A user can ignore the message by clicking “YES” the invalid data will be inputted.</li>
</ol>
<p>Here’s an example of the warning message a user will get:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/continue-no.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ol start="3">
<li><strong>Information:</strong> This is a permissive type of error alert as it only informs the user about invalid data inputted.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/continue-yes.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If the user clicks OK, the invalid gets inserted into the worksheet. If the user clicks on Cancel, the data gets deleted.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/error-alert-stop.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Give a title to the error alert and also provide a message for your users to see. When you’re done, click on OK, and your data validation rule has been set.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Data validation in Excel is one powerful feature you should utilize when creating an Excel spreadsheet.</p>
<p>You can use the data validation feature in Excel to make rules that will ensure the data inputted meets certain criteria or follows predefined rules. Setting a data validation rule helps to maintain data accuracy, consistency, and integrity within your Excel worksheet.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Google Apps Script Basics by Building a Tic Tac Toe Game ]]>
                </title>
                <description>
                    <![CDATA[ Google Sheets are powerful, and Apps Script makes them even more versatile and useful. Yes, you can use them for finance dashboards, personal budgets, and project management (and we'll cover these as future topics). But in this article, I'll go throu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-google-apps-script-basics-by-building-tic-tac-toe/</link>
                <guid isPermaLink="false">66b8de150cedc1f2a4f7067c</guid>
                
                    <category>
                        <![CDATA[ google apps script ]]>
                    </category>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Tue, 16 May 2023 16:58:37 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/Tic-Tac-Toe-Google-Sheet2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Google Sheets are powerful, and Apps Script makes them even more versatile and useful.</p>
<p>Yes, you can use them for finance dashboards, personal budgets, and project management (and we'll cover these as future topics). But in this article, I'll go through the basics of Apps Script by building a simple and playable Tic Tac Toe gameboard.</p>
<p>Here's the <a target="_blank" href="https://docs.google.com/spreadsheets/d/1I3mjQgfaZ9hFuUui6irpTdXg17TZXfK_jjtMvPrlGlM/edit?usp=sharing">link to the spreadsheet</a> we'll be making if you'd like to check it out while you follow along:</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQF91mJiUd4F5w/article-inline_image-shrink_1500_2232/0/1684162312276?e=1689811200&amp;v=beta&amp;t=ue0QHmYwX0I7oqirS6GZx66YXl5y_-zSkA6iPdDGKBM" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>Let's go gif</em></p>
<h3 id="heading-video-walkthrough-available">Video Walkthrough Available</h3>
<p>If you'd like to check out a video walkthrough of the Google Sheet, here you go:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/LYN3Cvlsflg" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-project-setup">Project Setup</h2>
<p>Create a new Google Sheet by either going to your Google Drive and selecting NEW -&gt; Google Sheet or by simply typing in sheets.new in the URL bar of your browser.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQGtAhxBgZCiPQ/article-inline_image-shrink_1500_2232/0/1684161563448?e=1689811200&amp;v=beta&amp;t=5TuDNK0iSggXlKST3fzl-wv5JV04qwbYizc3ev8F51E" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>screenshot of Google Drive</em></p>
<p>Since this is a gameboard, we are going to give it a little bit of formatting to look good, add data validation and conditional formatting to add functionality to the game, and create useable buttons for our scorecard.</p>
<p>Here's what we'll end up with:</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQFmLTdzhlehew/article-inline_image-shrink_1000_1488/0/1684161671894?e=1689811200&amp;v=beta&amp;t=2nJ0ZTnaCo2Dtq7u3zzSP7av2MHjtPtAyVp7dRQUwvY" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>screenshot of Tic Tac Toe Google Sheet</em></p>
<p>Let's remove gridlines, add borders to the gameboard and the scorecard, and set an alternative font for the board.</p>
<p>To get rid of gridlines, select View -&gt; Show -&gt; Gridlines to uncheck this option.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQFsYtEPWEAxjA/article-inline_image-shrink_400_744/0/1684161946643?e=1689811200&amp;v=beta&amp;t=r6rUrzy6NSj-KQDb0o7Jx64N_u3CmTWQJxr_KaTAtII" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>screenshot of Google Sheets view options</em></p>
<p>To get a nice square grid with large X's and O's, I set the row height and column width of rows 2 - 4 and columns B - D by highlighting them, right clicking, and selecting the resize options.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQGJGcSpYb2KyA/article-inline_image-shrink_1000_1488/0/1684162096408?e=1689811200&amp;v=beta&amp;t=uU37mbBSZBSMgi25ICD9r3hzAyCkepCmXAYx2ebCKsw" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>screenshot of resizing columns in Google Sheets</em></p>
<p>I chose 150 pixels for the height and width. You'll need to do these separately – you cannot change both the row height and column width at the same time.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQHzgbT4rS6f6w/article-inline_image-shrink_1000_1488/0/1684162162590?e=1689811200&amp;v=beta&amp;t=J-yExtOPV3icc6-YhGUmWESA0FUMzaJQu6N4qemzCwU" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>screenshot of resizing columns in Google Sheets</em></p>
<p>For the font size of the board, select 100, and for the Font, I am using Lexend. You can add additional Google Fonts from the toolbar dropdown:</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQF6Ss_zEGVSug/article-inline_image-shrink_1500_2232/0/1684162246754?e=1689811200&amp;v=beta&amp;t=R548yqr57k0ffuORMeqbZ3fmhQEWYL_QCiJv1EOGNo4" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>screenshot of Fonts options in Google Sheets</em></p>
<p>Add a border to the board and the scorecard areas by highlighting the cells and then selecting the border options from the toolbar.</p>
<p>Click and drag over cells to select the whole range, and hold down the CTRL button to click and drag a second area. You can style these at the same time.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQHGcJin6dOdtw/article-inline_image-shrink_1000_1488/0/1684162477801?e=1689811200&amp;v=beta&amp;t=lfxyTUvqmv7KjhZ5B2X9eDeVw9bWVm5rNiCBmReF6OE" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>screenshot of border options in Google Sheets</em></p>
<h2 id="heading-data-validation">Data Validation</h2>
<p>Highlight the gameboard (B2:D4) and select Data -&gt; Data validation from the menu.</p>
<p>This allows us to select Dropdown as the Criteria and add X and O as the two options to select.</p>
<p>Then click Advanced options and select Reject the input if the data is invalid, and plain text for the display style. This will keep the dropdown chips and handles from cluttering the gameboard.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQGj3dQDQ4QGuQ/article-inline_image-shrink_1500_2232/0/1684162681967?e=1689811200&amp;v=beta&amp;t=_HfNZ0C9L7tWucbWMMpzKf9gItYhkMP3G1cRlVGioxQ" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>screenshot of Data validation menu in Google Sheets</em></p>
<h2 id="heading-conditional-formatting">Conditional Formatting</h2>
<p>We'll use conditional formatting for our gameboard also. We need to check for all the winning conditions, and if one of the players gets three in a row, we will highlight those cells.</p>
<p>Keeping the gameboard highlighted, select Format -&gt; Conditional formatting.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQFJwi61h00_3g/article-inline_image-shrink_1000_1488/0/1684162938075?e=1689811200&amp;v=beta&amp;t=rdKBw21dV6Q82CgxNfiOG8Zg9N3fKXA135SauhAAYhA" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>screenshot of Format window in Google Sheets</em></p>
<p>There are eight conditions we'll check for three-in-a-row: going across x3, going down x3, and diagonal x2.</p>
<p>But we only need to write four formulas (two for the diagonals, one for across, and one for down) since we can use dollar ($) signs to drag the formula down and across for those.</p>
<p>For the down three-in-a-row:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//Apply to range B2:D2 </span>
=AND($B2=$C2,$B2=$D2,ISTEXT($B2))
</code></pre>
<p>For the across three-in-a-row:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//Apply to range B2:D2</span>
=AND(B$<span class="hljs-number">2</span>=B$<span class="hljs-number">3</span>,B$<span class="hljs-number">2</span>=B$<span class="hljs-number">4</span>,ISTEXT(B$<span class="hljs-number">3</span>))
</code></pre>
<p>For the diagonals we have to define them separately:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//Apply to range B2, C3, D4 </span>
=AND($B$<span class="hljs-number">2</span>=$C$<span class="hljs-number">3</span>,$B$<span class="hljs-number">2</span>=$D$<span class="hljs-number">4</span>,ISTEXT($B$<span class="hljs-number">2</span>))

<span class="hljs-comment">//Apply to range B4, C3, D2 </span>
=AND($B$<span class="hljs-number">4</span>=$C$<span class="hljs-number">3</span>,$B$<span class="hljs-number">4</span>=$D$<span class="hljs-number">2</span>,ISTEXT($B$<span class="hljs-number">4</span>))
</code></pre>
<p>We test for equality of each cell and whether there is anything in the cell with the <code>=ISTEXT()</code> function. By wrapping each item in an <code>=AND()</code> function, we'll only apply the formatting if all conditions are met.</p>
<p>I selected a green background for the conditional formatting.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQERGL76FWm8nA/article-inline_image-shrink_1500_2232/0/1684163627050?e=1689811200&amp;v=beta&amp;t=9C0IASvwa_KE1wm68iez-FxJ2YjmuwDRB42-ASak_5s" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>screenshot of conditional formatting window</em></p>
<h2 id="heading-apps-script">Apps Script</h2>
<p>Now for the scorecard logic. Let's open Apps Script by selecting Extensions -&gt; Apps Script from the menu:</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQHtQjZ3mujfUQ/article-inline_image-shrink_1500_2232/0/1684178999142?e=1689811200&amp;v=beta&amp;t=N5Wvx0y2md14-2Ih_PGj1_lHbKpW2mcEIPRNnRsvUAI" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>screenshot of Apps Script menu</em></p>
<p>We'll write four functions to handle our logic:</p>
<ol>
<li><code>xScore()</code> will increment X's score in the scorecard</li>
<li><code>oScore()</code> will increment O's score in the scorecard</li>
<li><code>clearBoard()</code> will clear the board but keep the scores</li>
<li><code>reset()</code> will clear the board and set the scores back to zero</li>
</ol>
<p>To make things more legible, let's set a few named ranges.</p>
<p>Highlight the gameboard again and select Data -&gt; Named ranges. Give this range a name of <strong>Board</strong>. Do the same for cells G4 and H4 for <strong>xScore</strong> and <strong>oScore</strong>, respectively.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQHS7_YVdCFbog/article-inline_image-shrink_1500_2232/0/1684163925497?e=1689811200&amp;v=beta&amp;t=8-jk-X5iea045w1ZBkCqiExObkF6c4A572zR4dqIrI0" alt="No alt text provided for this image" width="600" height="400" loading="lazy"></p>
<p>Now for the scores, we'll have the exact same function for each using only the two different ranges: xScore for X and oScore for O. Here's how those will look using the xScore as an example:</p>
<p><strong><code>xScore()</code> &amp; <code>oScore()</code>:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">xScore</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> sheet = SpreadsheetApp.getActive(); 
    <span class="hljs-keyword">var</span> xScore = sheet.getRangeByName(<span class="hljs-string">'xScore'</span>).getValue();
    sheet.getRangeByName(<span class="hljs-string">'xScore'</span>).setValue(xScore+<span class="hljs-number">1</span>); clearBoard();
}
</code></pre>
<ul>
<li>Line 1: This sets a variable (we'll do this in each function) for the active spreadsheet.</li>
<li>Line 2: This sets a variable for xScore as the value in the named range xScore (cell G4)</li>
<li>Line 3: This sets a new value for the xScore cell as whatever it was plus 1.</li>
<li>Line 4: This runs the clearBoard() function which we'll write next...</li>
</ul>
<p><strong><code>clearBoard()</code>:</strong></p>
<p>This will simply clear the gameboard but leave the score board untouched.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">clearBoard</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> sheet = SpreadsheetApp.getActive();
    <span class="hljs-keyword">let</span> board = sheet.getRangeByName(<span class="hljs-string">'Board'</span>);
    board.clearContent(); 
}
</code></pre>
<ul>
<li>Line 1: Our sheet variable again.</li>
<li>Line 2: Our board variable. This is grabbing the range B2:D4 which we named 'Board'</li>
<li>Line3: This built-in <code>clearContent()</code> method simply clears everything in those cells. Pretty simple.</li>
</ul>
<p><strong><code>reset()</code>:</strong></p>
<p>Now we need a function to set the score board and gameboard back to their original states.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reset</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> sheet = SpreadsheetApp.getActive(); 
    sheet.getRangeByName(<span class="hljs-string">'xScore'</span>).setValue(<span class="hljs-number">0</span>);
    sheet.getRangeByName(<span class="hljs-string">'oScore'</span>).setValue(<span class="hljs-number">0</span>); clearBoard(); 
}
</code></pre>
<ul>
<li>Line 1: our active sheet</li>
<li>Line 2: we grab our xScore range and set its value to 0.</li>
<li>Line 3: we do the same for our oScore</li>
<li>Line 4: we run the reset function to handle the gameboard.</li>
</ul>
<p>And that's it! Now we can run any of these functions from within the Apps Script editor and see that they work.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQFUTfyjYKeECQ/article-inline_image-shrink_1000_1488/0/1684178952423?e=1689811200&amp;v=beta&amp;t=ek0cIfi0cCqZfWKM7q7ygA7n18pKwMD5wdqUVizCQjU" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>screenshot of running code within Apps Script editor</em></p>
<h2 id="heading-how-to-create-buttons">How to Create Buttons</h2>
<p>It would be a lot nicer to have buttons in our actual spreadsheet to be able to run the functions.</p>
<p>To do this, we'll draw a button and then assign a script to it.</p>
<p>Select Insert -&gt; Drawing from the menu.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQEmlXrm9lNOjw/article-inline_image-shrink_1500_2232/0/1684179236609?e=1689811200&amp;v=beta&amp;t=wSn2IgbM2H6_flsNE0CecTzLqKj9K2ILIgCDL9N5x9w" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>Screenshot of Insert menu in Google Sheets</em></p>
<p>You can draw anything you'd like, but I chose the basic rounded rectangle.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQFbc8Vp8xMAEw/article-inline_image-shrink_400_744/0/1684179297444?e=1689811200&amp;v=beta&amp;t=M7QO7ZdcylQ6W4grOmguGY3aI_S-G-cpAVWiJOiyMcc" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>Screenshot of shapes in Google Sheets drawings menu</em></p>
<p>Double click in the shape to add text, and resize, recolor, restyle as needed.</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQHSkIBOsRvNdg/article-inline_image-shrink_1000_1488/0/1684179429349?e=1689811200&amp;v=beta&amp;t=9G87KKPY_efHEOTU_K2POBbUzeSfFlbs5nG282Oo4Gc" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>Screenshot of button in Google Sheets</em></p>
<p>Once you've created your button, click Save and Close. Then resize and position it where you'd like it in the Google Sheet. I've put mine right under the scorecard, and I made one for each score as well as a reset button.</p>
<p>Finally, to make the button work, click the three little dots at the top right of the button and select <strong>assign script</strong>. Then type in the name of the script (without the parentheses).</p>
<p><img src="https://media.licdn.com/dms/image/D5612AQGCHPMJ8FW-hw/article-inline_image-shrink_1500_2232/0/1684179559428?e=1689811200&amp;v=beta&amp;t=41p0tXKvG3Moj8bTJAI45nUhcZAUjhzPNoSbD_IP57I" alt="No alt text provided for this image" width="600" height="400" loading="lazy">
<em>Screenshot of assigning a script to a button in Google Sheets</em></p>
<p>Now, all you've got to do is click one of the buttons and the assigned script will run 🔥.</p>
<p>Two notes:</p>
<ol>
<li>The first time you run a script, there will be a pop-up dialog box asking you to accept the security allowances. It's a safety net to make sure you know you're running the code that's written in Apps Script, and to examine it if you didn't write it. You'll need to click through those and accept the risk to allow it to run.</li>
<li>If you need to move a button after assigning the script, you may get frustrated when clicking it doesn't bring up the three dots for the menu and only runs the script. To get around this and allow for movement and the three dot menu, right click the button.</li>
</ol>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>I hope this has been helpful for you!</p>
<p>Please subscribe to <a target="_blank" href="https://www.youtube.com/@eamonncottrell?sub_confirmation=1">my YouTube channel here</a> for more content like this.</p>
<p>Have a great one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Google Apps Script – Build a Paint By Numbers Spreadsheet ]]>
                </title>
                <description>
                    <![CDATA[ Spreadsheets are great for financial modeling, but they're also capable of displaying pixel art.  In this Apps Script tutorial, we'll build a paint by numbers spreadsheet using conditional formatting and a script that "paints" a blank spreadsheet. Yo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-google-apps-script-build-a-paint-by-numbers-spreadsheet/</link>
                <guid isPermaLink="false">66b8de180cedc1f2a4f7067f</guid>
                
                    <category>
                        <![CDATA[ google apps script ]]>
                    </category>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Mon, 24 Apr 2023 21:12:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/Google-Apps-Script-Paint-by-Numbers-Spreadsheet-final.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Spreadsheets are great for financial modeling, but they're also capable of displaying pixel art. </p>
<p>In this Apps Script tutorial, we'll build a paint by numbers spreadsheet using conditional formatting and a script that "paints" a blank spreadsheet.</p>
<p>You'll learn how to:</p>
<ol>
<li>Import data</li>
<li>Apply proper data visualization formatting to it</li>
<li>Code a couple of Apps Script functions to make it interactive. </li>
</ol>
<p>Let's do it 🎨</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/giphy.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Tenacious D rocking out</em></p>
<h2 id="heading-video-walkthrough">Video Walkthrough</h2>
<p>Yes, I've got a full walkthrough for you. Pull this up as you read to reference and follow along 👇</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/zNqcLWGJlvQ" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>Demo sheet with Pikachu: <a target="_blank" href="https://docs.google.com/spreadsheets/d/1Zu0B0dE_N4UrgAAzlWKqbpmz2TL_qr9GYWS451O7UL0/edit#gid=0">https://docs.google.com/spreadsheets/d/1Zu0B0dE_N4UrgAAzlWKqbpmz2TL_qr9GYWS451O7UL0/edit#gid=0</a></p>
<p>Demo sheet with Volcano: <a target="_blank" href="https://docs.google.com/spreadsheets/d/11lOVseXtpB6xWxhrmZr1LfImI75TBDbof6mkFzz0ck4/edit#gid=0">https://docs.google.com/spreadsheets/d/11lOVseXtpB6xWxhrmZr1LfImI75TBDbof6mkFzz0ck4/edit#gid=0</a></p>
<p>You can make an editable copy of either of these by selecting <code>File -&gt; Make a copy</code>.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>Everything we're doing today is built on some simple formatting. We are going to have cells turn certain colors based on the number inside them.</p>
<p>See the pic below where all the blue cells have the number 15 in them. By setting the color of the font and the background to blue, we can create the effect of the cells being a solid color.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-207.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of Pikachu pixel artwork</em></p>
<p>We can make our own number grid, but there are a ton available. I print these for my kids to color, and we can import them to our spreadsheet with a couple clicks.</p>
<p><a target="_blank" href="https://www.coloringsquared.com/worksheet/volcano-numbers-coloring-page/">Here's the volcano grid</a> I used in the walkthrough video.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-226.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of volcano color by number grid</em></p>
<p>When I first recorded the walkthrough video, I was unable to copy and paste from the PDF. When I did, it pasted every number in one cell. </p>
<p>Instead, by opening in Microsoft Word first and then copying and pasting from there, I was able to bring the number grid into the Google Sheet.</p>
<p>Since then, I've also found that when copying and pasting from the PDF, sometimes it will bring the numbers in to the first cell in each row:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-209.png" alt="Image" width="600" height="400" loading="lazy">
<em>picture of Google Sheets number grid</em></p>
<p>This doesn't work, either, because we need each number in its own cell. But, by applying the <code>=SPLIT()</code> function, we can achieve this easily. </p>
<p><code>=SPLIT(A1," ")</code> will split each value in the cell by the empty spaces. So, all the numbers are pulled out into their own cells in the row.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-210.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of Split function in Google Sheets</em></p>
<p>Once all the numbers are in individual cells, apply some formatting to the spreadsheet so that every cell is a square. Resize as big or as small as you'd like. I chose a row and column height of 30px.</p>
<p>To do this, select the column headers by clicking and dragging from A all the way to the end of the columns. Right click anywhere in the range, and select <code>Resize columns</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-211.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of resizing columns in Google Sheets</em></p>
<p>Do the same for the rows, specifying 30px for each.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-212.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of resizing rows in Google Sheets</em></p>
<p>Turn off the gridlines by selecting <code>View -&gt; Show -&gt; Gridlines</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-213.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of View options in Google Sheets</em></p>
<h2 id="heading-conditional-formatting">Conditional Formatting</h2>
<p>Select the entire range where all the numbers are and then click <code>Format -&gt; Conditional formatting</code>. </p>
<p>Click <code>Add new rule</code> and under Format rules, select <code>Is equal to</code> from the dropdown menu.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/equal.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of conditional formatting in Google Sheets</em></p>
<p>Under Formatting style, follow the color key from the coloring page you selected and adjust the font and background colors according to each number. </p>
<p>In our example, all the number 10s need to be blue, so we enter 10 and then have the same blue for both background and font colors:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-215.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of color options in Google Sheets</em></p>
<h3 id="heading-important-note">⭐Important Note</h3>
<p>Because of the script we're writing and how we're triggering it, you need to alter the HEX code for one of these two numbers. If they are the exact same, it will cause an error later. </p>
<p>So, first enter the same color for both, then open one and select the plus icon in the custom color swatch.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/custom.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of custom colors in Google Sheets</em></p>
<p>Manually change one value in the HEX code by one digit. In the example, I changed it from <code>#0b5294</code> to <code>#0b5394</code>. Visually, it will still look the same. If this is confusing, be sure to check out the <a target="_blank" href="https://youtu.be/zNqcLWGJlvQ?t=159">walkthrough video at 02:39</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-216.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of custom colors in Google Sheets</em></p>
<p>Do this for each color in your piece of art, and you'll have a gorgeous piece of pixel artwork in your spreadsheet. This alone is rewarding! 😀</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-217.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of volcano pixel art in Google Sheets</em></p>
<h2 id="heading-apps-script-setup">Apps Script Setup</h2>
<p>Name the sheet that we're on by double clicking <code>Sheet1</code> at the bottom. We'll call it "art". Then make a new sheet by clicking the plus icon on the bottom bar. Name it "canvas".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-219.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of sheet names in Google Sheets</em></p>
<p>Setup the canvas in the same way we did at the beginning, only without the conditional formatting. Make everything the same size, remove the gridlines, and add a border around the <code>B2:T21</code> range that will serve as a frame.</p>
<p>Now, we need to make buttons to toggle in each cell. In Google Sheets, the way to do this is by adding checkboxes to all the cells. Checkboxes will hold either a <code>true</code> or <code>false</code> value, and when we click them, they'll change back and forth.</p>
<p>Select our full range again, and select <code>Data -&gt; Data validation</code>. Change the criteria to <code>Checkbox</code> and under Advanced options select <code>Reject the input</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-227.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of data validation rules in Google Sheets</em></p>
<p>This will give our script something to be triggered by.</p>
<p>Format these checkboxes in the same way we did our conditional formatting: make the background white: <code>#ffffff</code>, and the font color just slightly different: <code>#fffeff</code>. Then, give them a huge font size, like 200. This will allow for us to click anywhere in the cell and not run the risk of clicking just outside the border of the box itself.</p>
<p>Now, let's open our code editor by selecting <code>Extensions -&gt; Apps Script</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-221.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of Extensions menu in Google Sheets</em></p>
<h2 id="heading-script-logic">Script Logic</h2>
<p>We need to copy and paste the formatting of individual cells every time we click the blank cells in our canvas.</p>
<p>To do this, we'll use an <code>onEdit(e)</code> trigger method built into Apps Script.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">onEdit</span>(<span class="hljs-params">e</span>) </span>{
  <span class="hljs-comment">//get current sheet</span>
  <span class="hljs-keyword">var</span> sheet = SpreadsheetApp.getActiveSheet();

  <span class="hljs-comment">// if we're not on the art sheet...</span>
  <span class="hljs-keyword">if</span>(sheet.getName() != <span class="hljs-string">"art"</span>){
</code></pre>
<p>First, we'll grab the active sheet as a variable. Then, making sure we're not on the "art" sheet, we'll go through the steps to grab and paste the formatting we need...</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// get the active cell and it's row, column reference</span>
<span class="hljs-keyword">var</span> activeRange = sheet.getActiveCell();
<span class="hljs-keyword">var</span> row = activeRange.getRow();
<span class="hljs-keyword">var</span> column = activeRange.getColumn();
</code></pre>
<p>Within our conditional if statement, we'll make three more variables so that we can grab the position of the cell we're in.</p>
<p>Then we need to go to our "art" sheet and grab the formatting from the corresponding cell.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> artRange = SpreadsheetApp.getActive().getSheetByName(<span class="hljs-string">"art"</span>).getRange(row,column);
<span class="hljs-comment">// get the background color from the same reference in art sheet</span>
<span class="hljs-keyword">var</span> backgroundColor = artRange.getBackground();
<span class="hljs-keyword">var</span> fontColor = artRange.getFontColor();
</code></pre>
<p>We'll make another three variables: one for the artRange which grabs the range from the "art" sheet using the <code>row</code> and <code>column</code> that we're on in the "canvas" sheet. And then two variables for the colors: one for background and one for font.</p>
<p>Now all we need to do is set the "canvas" sheet's cell to the colors we just grabbed. I've also chosen to make it toggle back to a blank white cell if it's already been colored. So we'll use another if statement to handle that:</p>
<pre><code class="lang-javascript">trueFalse = activeRange.getValue();
<span class="hljs-keyword">if</span>(trueFalse){
      <span class="hljs-comment">// set activeRange with that backgroundColor</span>
      activeRange.setBackground(backgroundColor);
      activeRange.setFontColor(fontColor);
    }
    <span class="hljs-keyword">else</span>{
      activeRange.setBackground(<span class="hljs-string">'#ffffff'</span>);
      activeRange.setFontColor(<span class="hljs-string">'#fffeff'</span>);
    }
</code></pre>
<p>First, we set a trueFalse variable equal to the activeRange's value. This is either <code>true</code> or <code>false</code> depending on the state of the checkbox.</p>
<p>If it's false (the checkbox isn't checked), then we set the background and font colors using the variables we grabbed from our "art" sheet.</p>
<p>Here's the full <code>onEdit(e)</code> code:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">onEdit</span>(<span class="hljs-params">e</span>) </span>{
  <span class="hljs-comment">//get current sheet</span>
  <span class="hljs-keyword">var</span> sheet = SpreadsheetApp.getActiveSheet();

  <span class="hljs-comment">// if we're not on the art sheet...</span>
  <span class="hljs-keyword">if</span>(sheet.getName() != <span class="hljs-string">"art"</span>){

    <span class="hljs-comment">// get the active cell and it's row, column reference</span>
    <span class="hljs-keyword">var</span> activeRange = sheet.getActiveCell();
    <span class="hljs-keyword">var</span> row = activeRange.getRow();
    <span class="hljs-keyword">var</span> column = activeRange.getColumn();

    <span class="hljs-keyword">var</span> artRange = SpreadsheetApp.getActive().getSheetByName(<span class="hljs-string">"art"</span>).getRange(row,column);

    <span class="hljs-comment">// get the background color from the same reference in art sheet</span>
    <span class="hljs-keyword">var</span> backgroundColor = artRange.getBackground();
    <span class="hljs-keyword">var</span> fontColor = artRange.getFontColor();

    Logger.log(backgroundColor)
    Logger.log(fontColor)

    trueFalse = activeRange.getValue();

    <span class="hljs-keyword">if</span>(trueFalse){
      <span class="hljs-comment">// set activeRange with that backgroundColor</span>
      activeRange.setBackground(backgroundColor);
      activeRange.setFontColor(fontColor);
    }
    <span class="hljs-keyword">else</span>{
      activeRange.setBackground(<span class="hljs-string">'#ffffff'</span>);
      activeRange.setFontColor(<span class="hljs-string">'#fffeff'</span>);
    }
  }
}
</code></pre>
<h2 id="heading-reset-function">Reset Function</h2>
<p>As an added feature, we'll add an actual button to reset the canvas. To do this, we'll make a new function in our Apps Script code editor. </p>
<p>We'll grab the sheet and all the checkboxes as variables. To get the checkboxes, we'll use the <code>getRangebyName()</code> method on our 'canvasArt' range.</p>
<p>Then, Apps Script makes it pretty easy with built in methods. We set the value of all the checkboxes to <code>false</code>, the background color to <code>#ffffff</code>, and the font color to <code>#fffeff</code>.</p>
<p>Here's the full <code>reset()</code> code:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reset</span>(<span class="hljs-params"></span>)</span>{
  <span class="hljs-keyword">var</span> sheet = SpreadsheetApp.getActive();
  <span class="hljs-keyword">var</span> checkboxes = sheet.getRangeByName(<span class="hljs-string">'canvasArt'</span>);
  checkboxes.setValue(<span class="hljs-literal">false</span>);
  checkboxes.setBackground(<span class="hljs-string">"#ffffff"</span>);
  checkboxes.setFontColor(<span class="hljs-string">"#fffeff"</span>);
}
</code></pre>
<h2 id="heading-trigger-with-button">Trigger with Button</h2>
<p>To make a button in the spreadsheet, select <code>Insert -&gt; Drawing</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-222.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of Insert menu in Google Sheets</em></p>
<p>Select the rounded rectangle shape and drag it onto the grid.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-223.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of Shapes menu in Google Sheets</em></p>
<p>Double click into the shape to write "CLEAR". Adjust the font and colors as you see fit.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-224.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of button drawing in Google Sheets</em></p>
<p>Click Save and Close and then drag it to re-size and reposition onto your sheet at the bottom of the canvas.</p>
<p>Once you've positioned it, click the three circles in the top right, select <code>Assign script</code>, and type in the name of the script you'd like it to trigger (in our case, <code>reset</code>). </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-225.png" alt="Image" width="600" height="400" loading="lazy">
<em>Picture of assigning script to button in Google Sheets</em></p>
<p>Now, when you click this button, that script will run and clear the whole art canvas.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope this has been helpful for you! I had a great time making this, and I have more game-type spreadsheet content coming soon.</p>
<p>Come follow me on <a target="_blank" href="https://www.youtube.com/@eamonncottrell">YouTube</a>, and say hey over on <a target="_blank" href="https://www.linkedin.com/in/eamonncottrell/">LinkedIn</a>.</p>
<p>Have a great one! 👋</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Google Sheets – Learn Advanced Functions by Building a Zelda Dashboard ]]>
                </title>
                <description>
                    <![CDATA[ In this article we'll build a dashboard inspired by the recipes in Zelda: Breath of the Wild.  Our dashboard will have multiple data validation dropdown selections for us to choose ingredients. By using a =Query() function, we'll then display the rec... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/google-sheets-advanced-functions-by-building-a-zelda-dashboard/</link>
                <guid isPermaLink="false">66b8ddea0cedc1f2a4f70676</guid>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Thu, 13 Apr 2023 17:31:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/Zelda-Walkthrough.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article we'll build a dashboard inspired by the recipes in Zelda: Breath of the Wild. </p>
<p>Our dashboard will have multiple data validation dropdown selections for us to choose ingredients. By using a <code>=Query()</code> function, we'll then display the recipes that contain any combination of the selected ingredients.</p>
<p>Let's go!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/letsgo.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of man saying, "here we go!"</em></p>
<h2 id="heading-final-product">Final Product</h2>
<p>Here's what the finished dashboard will look like. It's not overly complicated, and the tools and techniques we'll use to get the data, clean it, and display it dynamically are quite valuable.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-7.28.35-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>picture of the Zelda dashboard</em></p>
<p><strong><a target="_blank" href="https://docs.google.com/spreadsheets/d/1S_oWlUdbMCEm5B12oYoUDvdMwKLZ5oFr4XqxQ_9rVo4/edit?usp=sharing">Here's the source code Google Sheet</a>.</strong> Open this up to follow along and double check some of the code as you go through the article</p>
<p>You can make an editable copy of this by selecting <code>File -&gt; Make a Copy</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-7.36.29-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-walkthrough-video">Walkthrough Video</h3>
<p>If you'd like to see a video of me building this from scratch, here is a time-lapse 14min video with me narrating the steps:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/EUBpyTiaCV0" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-project-setup">Project Setup</h2>
<p>The first thing we need is data. In our case, we're going to use the <code>IMPORTHTML()</code> function to get data from IGN. <code>IMPORTHTML()</code> allows us to reference a URL, specify whether to search the URL for "tables" or "lists", and then by providing an index number, import the table or list from the URL.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-129.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of importhtml docs</em></p>
<p>IGN has a handy recipe cookbook <a target="_blank" href="https://www.ign.com/wikis/the-legend-of-zelda-breath-of-the-wild/All_Recipes_and_Cookbook">here</a>.</p>
<p>We'll place the URL in a cell in our Google Sheet because after inspecting the page, we see that the recipes are contained within several tables, so we'll need to use multiple import statements.</p>
<p>I've put the URL in <code>D3</code> and we're ready to import all the tables. In order to do this in one fell swoop, we can use curly brackets. In Google Sheets, curly brackets create arrays.</p>
<p>By wrapping multiple <code>IMPORTHTML()</code> statements in curly brackets, we create an array of all those imports. As a final touch, we can wrap the whole thing in a <code>UNIQUE()</code> function to ensure that no duplicate recipes (or in our case, table headers) are brought over to our data tab.</p>
<p>Here's the code:</p>
<p>```google sheets
=UNIQUE({IMPORTHTML(D3,"table",3);
IMPORTHTML(D3,"table",4);
IMPORTHTML(D3,"table",5);
IMPORTHTML(D3,"table",6);
IMPORTHTML(D3,"table",7);
IMPORTHTML(D3,"table",8);
IMPORTHTML(D3,"table",9)})</p>
<pre><code>
This gives us the data, but we need to clean it up. Specifically, we need to get rid <span class="hljs-keyword">of</span> the asterisks <span class="hljs-keyword">in</span> the meal titles and the dashes, extras spaces, and line breaks <span class="hljs-keyword">in</span> the ingredient lists.

![Image](https:<span class="hljs-comment">//www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-7.46.34-PM.png)</span>
_picture <span class="hljs-keyword">of</span> uncleaned imported data_

## How to Clean the Data

For the titles, we<span class="hljs-string">'ll use the `MID()` and `LEN()` functions.

```google sheets
//For first row of Meal Titles
=MID(A6,2,LEN(A6)-2)</span>
</code></pre><p><code>MID()</code> returns a section of the cell's contents starting at one index and ending at another. We want to grab the contents after the first asterisk, so we'll use 2 as the first index. And then we'll use <code>LEN()-2</code> to find the length of the cell's contents minus 2 for the ending index.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-8.09.57-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of cleaning data in Google Sheet</em></p>
<p>For the ingredients, we'll first use <code>TRIM(CLEAN())</code> to remove non-printable characters and extra spaces. Then, we'll use <code>ARRAYFORMULA(TRIM(SPLIT()))</code> to get each remaining ingredient into its own cell.</p>
<p>```google sheets
//For first row of Ingredients
=ARRAYFORMULA(TRIM(SPLIT(C6,"-")))</p>
<pre><code>
![Image](https:<span class="hljs-comment">//www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-8.15.06-PM.png)</span>
_Screenshot <span class="hljs-keyword">of</span> TRIM, SPLIT and ARRAY FORMULA_

Now that we have our ingredients split into separate cells, <span class="hljs-keyword">let</span><span class="hljs-string">'s name some ranges. This will make life easier as we build the dashboard in a moment. 😀

Selecting each column of the ingredients, go to `Data -&gt; named ranges` and name them `Ingredient1`, `Ingredient2`, `Ingredient3`, `Ingredient4`, and `Ingredient5`. 

![Image](https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-8.20.43-PM.png)
_screenshot of named ranges menu_

Also, select the entire cleaned data range: our meal titles and our individual ingredient columns, and name this range `RecipeList`.

![Image](https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-8.24.40-PM.png)
_Screenshot of cleaned full recipe list_

## How to Get All Unique Ingredients

Create a new sheet by clicking the `+` button at the bottom left of the window and name this sheet `Ingredients`.

![Image](https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-8.26.05-PM.png)
_Screenshot of add new sheet button_

We now need all the unique ingredients pulled out into a range which we'</span>ll name <span class="hljs-string">`allIngredients`</span>.

To <span class="hljs-keyword">do</span> <span class="hljs-built_in">this</span>, we<span class="hljs-string">'ll use the `UNIQUE()` function and all the ingredient named ranges wrapped in curly brackets.

```appscript
=UNIQUE({Ingredient1;
Ingredient2;
Ingredient3;
Ingredient4;
Ingredient5})</span>
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-8.28.41-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This gives us a unique list of ingredients that we'll use as we build the dropdown menus in our dashboard.</p>
<h2 id="heading-how-to-make-the-dashboard">How to Make the Dashboard</h2>
<p>Create another new sheet and name it <code>Dashboard</code>. Here's where the fun begins. 🔥</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/fun.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of woman saying, fun will now commence.</em></p>
<p>The first thing we need are some dropdown menus containing all the possible ingredients.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-8.32.55-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of dropdown menu</em></p>
<p>You may either right click in a cell and select Dropdown, or select <code>Data -&gt; Data validation</code> from the Toolbar.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-8.33.35-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of Dropdown option in Google Sheets</em></p>
<p>Under criteria, select <code>Dropdown (from a range)</code>. And in the range, we can input the named range we just created from our Ingredients sheet: <code>=allIngredients</code>.</p>
<p>This will populate all the ingredients beneath the selection. If you'd like, you can even customize the color and appearance options for these. Since there are so many, I left them as default.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-8.34.46-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of data validation rules.</em></p>
<p>Simply copy and paste this cell two more times and we have our three identical dropdown menus.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-8.37.19-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of 3 dropdown menus</em></p>
<h3 id="heading-logic">Logic</h3>
<p>We want to handle a few different cases in our dashboard. For any selected ingredient or combination of ingredients, we want to query our <code>RecipeList</code> named range for those ingredients and return the full corresponding recipe.</p>
<p>There are eight possible combinations for the dropdown menus being filled out: </p>
<ol>
<li>none</li>
<li>all</li>
<li>only the first</li>
<li>only the second</li>
<li>only the third</li>
<li>first and second</li>
<li>first and third</li>
<li>second and third.</li>
</ol>
<p>We need to feed a query statement with different values depending on which of the above states is true.</p>
<p>Let's make another new sheet and name it <code>Formula</code> to spell out and keep track of this logic.</p>
<p>We need a simple test for TRUE or FALSE for each of the possibilities. And to do this, we'll simply test whether or not each of the dropdown menus are blank or contain text. </p>
<p>Conveniently, Google Sheets has two functions that do exactly that: <code>ISBLANK()</code> and <code>ISTEXT()</code>.</p>
<p>We'll do some more range naming to make things more legible and then test for each condition.</p>
<p>I've named the three dropdown menu ranges on the Dashboard <code>Dash9</code>, <code>Dash10</code> and <code>Dash11</code>.</p>
<p>Here's the code to test for when the first and third dropdown menus are filled out:</p>
<p>```google sheets
=IF(AND(ISTEXT(Dash9),ISTEXT(Dash10),ISBLANK(Dash11)),true,false)</p>
<pre><code>
![Image](https:<span class="hljs-comment">//www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-8.44.27-PM.png)</span>
_Screenshot <span class="hljs-keyword">of</span> logic tests_

The <span class="hljs-string">`IF`</span> statement returns <span class="hljs-literal">true</span> or <span class="hljs-literal">false</span> based on the nested <span class="hljs-string">`AND`</span> statement which combines the <span class="hljs-string">`ISTEXT`</span> and <span class="hljs-string">`ISBLANK`</span> statements <span class="hljs-keyword">for</span> each dropdown menu.

&gt; Stay <span class="hljs-keyword">with</span> me! It<span class="hljs-string">'s all about to come together! 👊

Now, in order to feed the dropdown menu options to our query statement (which I promise we'</span>re about to write!) we need to string it together <span class="hljs-keyword">with</span> bar lines which will <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">like</span> <span class="hljs-title">the</span> `<span class="hljs-title">OR</span>` <span class="hljs-title">operator</span> <span class="hljs-title">in</span> <span class="hljs-title">the</span> <span class="hljs-title">query</span>.

<span class="hljs-title">So</span>...<span class="hljs-title">in</span> `<span class="hljs-title">A1</span>` <span class="hljs-title">of</span> <span class="hljs-title">our</span> `<span class="hljs-title">Formula</span>` <span class="hljs-title">sheet</span>, <span class="hljs-title">we</span>'<span class="hljs-title">ll</span> <span class="hljs-title">use</span> <span class="hljs-title">an</span> `<span class="hljs-title">IFS</span>(<span class="hljs-params"></span>)` <span class="hljs-title">function</span> <span class="hljs-title">to</span> <span class="hljs-title">display</span> <span class="hljs-title">the</span> <span class="hljs-title">contents</span> <span class="hljs-title">of</span> <span class="hljs-title">one</span> <span class="hljs-title">or</span> <span class="hljs-title">more</span> <span class="hljs-title">of</span> <span class="hljs-title">the</span> `<span class="hljs-title">Dash9</span>`, `<span class="hljs-title">Dash10</span>` <span class="hljs-title">and</span> `<span class="hljs-title">Dash11</span>` <span class="hljs-title">ranges</span>. 

<span class="hljs-title">To</span> <span class="hljs-title">achieve</span> <span class="hljs-title">this</span> <span class="hljs-title">when</span> <span class="hljs-title">there</span> <span class="hljs-title">are</span> <span class="hljs-title">more</span> <span class="hljs-title">than</span> <span class="hljs-title">one</span> <span class="hljs-title">with</span> <span class="hljs-title">values</span>, <span class="hljs-title">we</span> <span class="hljs-title">use</span> <span class="hljs-title">the</span> `&amp;` <span class="hljs-title">operator</span> <span class="hljs-title">which</span> <span class="hljs-title">concatenates</span> <span class="hljs-title">the</span> <span class="hljs-title">value</span> <span class="hljs-title">in</span> <span class="hljs-title">the</span> `<span class="hljs-title">Dash</span>` <span class="hljs-title">cell</span> <span class="hljs-title">with</span> <span class="hljs-title">a</span> <span class="hljs-title">bar</span> <span class="hljs-title">line</span> <span class="hljs-title">within</span> <span class="hljs-title">quotes</span> (<span class="hljs-params"><span class="hljs-string">"|"</span></span>). <span class="hljs-title">And</span> <span class="hljs-title">the</span> <span class="hljs-title">result</span> <span class="hljs-title">is</span> <span class="hljs-title">shown</span> <span class="hljs-title">below</span>. 

```<span class="hljs-title">google</span> <span class="hljs-title">sheets</span>
=<span class="hljs-title">IFS</span>(<span class="hljs-params">B2,<span class="hljs-string">""</span>,
B3,Dash9,
B4,Dash10,
B5,Dash11,
B6,Dash9&amp;<span class="hljs-string">"|"</span>&amp;Dash10,
B7,Dash9&amp;<span class="hljs-string">"|"</span>&amp;Dash11,
B8,Dash10&amp;<span class="hljs-string">"|"</span>&amp;Dash11,
B9,Dash9&amp;<span class="hljs-string">"|"</span>&amp;Dash10&amp;<span class="hljs-string">"|"</span>&amp;Dash11</span>)</span>
</code></pre><p>We have our query value built. And it will change dynamically depending on which dropdown menus contain text.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-12-at-8.55.39-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of IFS Statement</em></p>
<h2 id="heading-query-statement">Query Statement</h2>
<p>Now, the hard work is done. Let's plug what we've created into a query statement on the Dashboard to make this all work!</p>
<p>Query will look at a range, in our case the <code>RecipeList</code> named range with all our meal names and ingredients, and return everything that matches the criteria we feed it. </p>
<p>We want to return a full recipe when our <code>Query</code> named range is matched to an ingredient in any of the five ingredient named ranges. </p>
<p>Here's the full code, and I'll explain it below.</p>
<p><code>google sheets
=if(Query="","",
QUERY(RecipeList,
"Select * 
WHERE E matches'"&amp;Query&amp;"' 
OR F matches '"&amp;Query&amp;"' 
OR G matches '"&amp;Query&amp;"' 
OR H matches '"&amp;Query&amp;"' 
OR I matches '"&amp;Query&amp;"'"))</code></p>
<p>First, if our <code>Query</code> is an empty string, we want nothing to be returned...this is when none of the dropdowns are filled in and the result will be an empty table on the dashboard.</p>
<p><code>Select *</code>: this means to select all, or return all the values in the query range. </p>
<p><code>WHERE E matches '"&amp;Query&amp;"'</code>: This is the beginning of the criteria. <code>E</code> is literally column E from our <code>Data</code> sheet. That's where the <code>Ingredient1</code> named range lives. <code>F</code> is where <code>Ingredient2</code> is...and so on.</p>
<p>By using <code>matches</code>, we are telling the query to see if any value in the <code>Query</code> named range matches any value in each of the specified ingredient columns. We have to use the funky syntax of single and double quotes to make the query function know that we're using that <code>Query</code> named range and not the word or string, "Query".</p>
<p>The bar lines in our <code>Query</code> named range functions as the OR operator, so when there are multiple ingredients in the dropdown list, the query statement looks in each column for either one <strong>or</strong> the other ingredient.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This was a ton of fun to make, and I hope you've been able to learn some valuable skills by following along. </p>
<p>We've imported data, cleaned it up, created named ranges, dropdown menus and dynamically changing logical tests...all for the sake of a query statement that returns the recipes we need based on the ingredient(s) we give it.</p>
<p><a target="_blank" href="https://www.youtube.com/@eamonncottrell?sub_confirmation=1">Come follow me on YouTube</a> where I'm making more content like this weekly. 👋</p>
<p>Have a great one!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Google Apps Script Code to Clear Data Ranges in Google Sheets ]]>
                </title>
                <description>
                    <![CDATA[ Google Apps Script allows you to write code in your spreadsheet. It functions like Visual Basic for Applications (VBA) does in Excel. They're both incredibly useful for executing more complicated actions or for automating repetitive tasks. In this ar... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-apps-script-to-clear-data-in-google-sheets/</link>
                <guid isPermaLink="false">66b8de27f805ffd579552e9c</guid>
                
                    <category>
                        <![CDATA[ google apps script ]]>
                    </category>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spreadsheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Wed, 29 Mar 2023 19:55:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/fcc-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Google Apps Script allows you to write code in your spreadsheet. It functions like Visual Basic for Applications (VBA) does in Excel. They're both incredibly useful for executing more complicated actions or for automating repetitive tasks.</p>
<p>In this article, I'll give you a brief overview of Google Apps Script by showing you how to do something very simple: clearing a bunch of data in your spreadsheet.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/homer-simple.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of Homer Simpson saying, of course, it's so simple.</em></p>
<h2 id="heading-what-is-apps-script">What is Apps Script?</h2>
<p>Good question. Though you may be familiar with the square grid that makes up the interface of most spreadsheets, you may not know that behind the scenes, there is a powerful cloud-based JavaScript platform. </p>
<p>Apps Script lets you write custom functions, automations, add-ons and more. The screenshot below is from <a target="_blank" href="https://developers.google.com/apps-script#:~:text=Apps%20Script%20is%20a%20cloud,automate%20tasks%20across%20Google%20products.">Google Workspace Docs</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-213.png" alt="Image" width="600" height="400" loading="lazy">
<em>Google Workspace docs</em></p>
<h2 id="heading-open-apps-script">Open Apps Script</h2>
<p><a target="_blank" href="https://docs.google.com/spreadsheets/d/1wmiSt2KnwTOX7wQZZaLnHXYIN9NBk_B487JJ4EHbnlc/edit?usp=sharing">Here is the link to the demo sheet</a> if you'd like to follow along and/or make a copy.</p>
<p>You can also build one with me by opening a new sheet: <a target="_blank" href="https://sheets.new">https://sheets.new</a>.</p>
<p>And here's a video walkthrough detailing everything we're about to do:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/PVoa7dp6pr0" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>For our example, we just need some data to clear. In my business we use this apps script to clear out templates once a month that we use weekly for inventory purposes.</p>
<p>We'll build a miniature version of this to practice with, but the principles we go over can be used on much larger scales where apps script can save a ton of time and effort.</p>
<p>Here's what our sheet will look like: four weeks worth of inventory and order amounts.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-209.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of order form in Google Sheets</em></p>
<p>We want an automated way to clear the data in the inventory and order columns.</p>
<p>Yes, you could simply select that range and hit delete or backspace. But if your spreadsheet is larger and more nuanced, there may be tens or hundreds of ranges to select.</p>
<p>And this is where Apps Script comes in super handy.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/assist.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of Bill Murray</em></p>
<p>To open Apps Script, go to <code>Extensions -&gt; Apps Script</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/open.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of Extensions Toolbar</em></p>
<p>🤔Now, what's better than working in a dapper spreadsheet? </p>
<p>Being able to write custom code for it! </p>
<p>From here, we're greeted with our old friend, the code editor. </p>
<p>We'll give this project a name of <code>Clear Range</code> at the top, and then making sure the code editor is selected on the left side-bar, we'll begin writing our first function, also named <code>clearRange</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/editor.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We can save our progress as we write by either pressing <code>CTRL + S</code> or clicking the save disk in the toolbar.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/save.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of apps script code editor</em></p>
<p>It wouldn't be coding with a console to debug ourselves, and sure enough, there is a <code>Logger.log()</code> method built in to Apps Script. Let's write our first Apps Script...script 😀 to log the message, <code>Hello console! :)</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">clearRange</span>(<span class="hljs-params"></span>) </span>{
  Logger.log(<span class="hljs-string">'Hello console! :)'</span>)
}
</code></pre>
<p>And here's what you should see when you hit the Run button in the toolbar: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/console.log.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of Logger.log() in Apps Script</em></p>
<p>Okay, so things are indeed working. Let's get to business with our actual script...</p>
<h2 id="heading-how-to-add-a-custom-menu">How to Add a Custom Menu</h2>
<p>We can execute our code within the code editor by clicking <code>Run</code>, but we don't want to open this up every time we use the code. So, let's add a custom menu to the toolbar inside our spreadsheet.</p>
<p>We've got two options here: creating a custom menu or creating an addon menu. The custom menu will function as a dropdown menu directly on the Toolbar to the right of the <code>Help</code> menu. The addon menu will display within the regular <code>Extensions</code> dropdown menu.</p>
<p>Let's add the custom menu. It can be helpful to copy methods from the <a target="_blank" href="https://developers.google.com/apps-script/reference/base/ui#createMenu(String)">Apps Script Docs</a> and then fit them to our purposes. That's what I've done below from the createMenu() method here:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">onOpen</span>(<span class="hljs-params">e</span>) </span>{
  SpreadsheetApp.getUi()
      .createMenu(<span class="hljs-string">'Clear Entries'</span>)
      .addItem(<span class="hljs-string">'Clear \'em all!'</span>, <span class="hljs-string">'clearRange'</span>)
      .addSeparator()
      .addToUi();
}
</code></pre>
<p>This creates a menu when the spreadsheet is opened named Clear Entries. Within the menu, there's a clickable item named Clear 'em all! that calls the <code>clearRange</code> function.</p>
<h2 id="heading-how-to-add-the-function">How to Add the Function</h2>
<p>Now, we need the function to do more than log a message to the console.</p>
<p>We can clear the contents of a range or ranges in a few ways. We'll do it here by naming the ranges that we will want to clear. This will prevent us from having to hard code cell references in case those change down the road as we modify the spreadsheet.</p>
<p>I've named each week's inventory and order columns as named ranges:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-255.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of named ranges</em></p>
<p>Then, in our function we make a variable to hold an array of all the named ranges, iterate over each one in a <code>forEach()</code> loop, and clear each range's contents using the <code>clearContent()</code> method.</p>
<p>Very simple, and only it takes a few lines of code:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">clearRange</span>(<span class="hljs-params"></span>)</span>{
  <span class="hljs-keyword">var</span> ss = SpreadsheetApp.getActive();
  <span class="hljs-keyword">var</span> ranges = ss.getNamedRanges();
  ranges.forEach(<span class="hljs-function"><span class="hljs-params">range</span> =&gt;</span> range.getRange().clearContent());
}
</code></pre>
<p>In the <a target="_blank" href="https://docs.google.com/spreadsheets/d/1wmiSt2KnwTOX7wQZZaLnHXYIN9NBk_B487JJ4EHbnlc/edit?usp=sharing">demo Google Sheet</a>, I included the alternative way to write this with A1 notation if you needed to not use the named ranges.</p>
<h2 id="heading-how-to-execute-the-function">How to Execute the Function</h2>
<p>When you first execute a function that requires access to your data, you'll be greeted by this Authorization screen.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-251.png" alt="Image" width="600" height="400" loading="lazy">
<em>authorization screenshot</em></p>
<p>Choose your Google account, click Advanced when you see the "Google hasn't verified this app" screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/verify.png" alt="Image" width="600" height="400" loading="lazy">
<em>Google verification screen</em></p>
<p>It will describe what the function trying to execute is going to have permission to access. Click Allow:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/sign.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot allowing permission to use our new function</em></p>
<p>Once you've allowed the permissions, you'll need to execute the function again for it to actually run this time. You'll see this running script dialog pop up at the top:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-256.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of running script dialog box</em></p>
<p>And, voilà!</p>
<p>We've cleared our range :)</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/clear-script_1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of the spreadsheet range clearing</em></p>
<h2 id="heading-summary">Summary</h2>
<p>I hope this has been a useful walkthrough for you, and that you learned something new. I use a version of this very script in the real world on a regular basis. It's an example of a pretty small thing that saves a ton of time and errors.</p>
<p>Come say hey and subscribe to my <a target="_blank" href="https://www.youtube.com/@eamonncottrell">YouTube channel over here</a>. I create walkthroughs and tech content weekly.</p>
<p>Have a great one! 👋</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
