{"id":20944910,"url":"https://github.com/liamca/excel-search-app","last_synced_at":"2025-03-13T04:17:38.060Z","repository":{"id":78151549,"uuid":"544966083","full_name":"liamca/excel-search-app","owner":"liamca","description":"Excel Search Application","archived":false,"fork":false,"pushed_at":"2022-10-04T14:09:48.000Z","size":384,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-19T21:41:40.650Z","etag":null,"topics":["azure","azuresearch","excel","powerquery","search"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/liamca.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-03T14:49:09.000Z","updated_at":"2023-05-12T17:29:00.000Z","dependencies_parsed_at":"2023-04-04T00:32:56.645Z","dependency_job_id":null,"html_url":"https://github.com/liamca/excel-search-app","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liamca%2Fexcel-search-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liamca%2Fexcel-search-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liamca%2Fexcel-search-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liamca%2Fexcel-search-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/liamca","download_url":"https://codeload.github.com/liamca/excel-search-app/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243335420,"owners_count":20274904,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","azuresearch","excel","powerquery","search"],"created_at":"2024-11-18T23:45:56.155Z","updated_at":"2025-03-13T04:17:38.043Z","avatar_url":"https://github.com/liamca.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# How to Create an Excel Search Application\n\nSearch applications are typically supported through Web applications, however, these can often be time consuming to create and often the people that need to create these applications may not have the development background or time to create these applications. Furthermore, there may be times where a browser is not the preferred place to work with the data and it may be productivity tools such as Excel that are more preferrable. This tutorial is intended to show how to create a search applicaiton from within Excel that requires no-coding (other than some Power Query scripting) with very little effort. Since this tutorial leverages Power Query, with very few changes it could be adapted to provide the same functionality in Power BI.\n\n![Search App in Excel](images/search-app-final.png)\n\n## What is Needed\n- This tutorial leverages [Azure Cognitive Search](https://learn.microsoft.com/azure/search/search-what-is-azure-search) as the search engine and you will require an Azure Subscription ([Free Subscription](https://azure.microsoft.com/free/))\n- Excel \n\n## Getting Started\n### Create the Azure Cognitive Search Index\nFor this tutorial we will use a sample index that comes with Azure Cognitive Search called Hotels, which is a data source consisting of fictitious hotel data. We will use this dataset to allow us to search and filter the hotel rooms within this search index.\n\nFollow the instructions in [this page](https://learn.microsoft.com/en-us/azure/search/search-get-started-portal) to create and explore the hotel index from the Azure Portal.\n\n### Enable CORS\nSince the Excel application will connect directly to the search index, we need to enable CORS for this index. To do this, in the Azure Portal choose the \"Indexes\" tab and click on the \"hotels-sample-index\". Click \"CORS\" and select \"All\" as the allowed origin type and choose \"Save\".\n\n![Enable CORS](images/cors.png)\n\n### Create a Query API Key\nAll queries to Azure Cognitive Search need to be authenticated. Since we will be querying from Excel, we will want to create a Query API key as this key has limited priviledges to the search index and also sufficient priviledges to suppor the Excel search application. To create this key, choose the \"Keys\" option from the main page of your Azure Cognitive Search service.\n\nUnder \"Manage Query Keys\" choose \"Add\". Name the key \"excel-search-app\" and choose \"Done\".\n\nCopy the resulting Query Key and save this for a future step.\n\n![Create Query Key](images/query-key.png)\n\n## Create the Excel Search Application\nNow that we have a search index, we will create a new Excel spreadsheet for this search application. In this step we will leverage Power Query to execute the search queries that are shown. To get started create a new Excel blank spreadsheet and name it excel-hotel-search-app.xlsx.\n\nNext we will create some Power Queries. The first one we will create will retrieve all of the unique facet values (categories) for a particular field. For our tutorial we will use the facetable fields Category \u0026 ParkingIncluded. \n\n### Retrieve all Categories \nTo create a query to get all the Categories, choose Data -\u003e Get Data -\u003e From Other Sources -\u003e Blank Query. This will open Power Query and create a query titled Query1. Right click and choose \"Rename\" and name the query \"facetCategories\".\n\n![Rename Query](images/pq-01-rename-query.png)\n\nRight click on facetCategories and choose \"Advanced Editor\".\nTo allow us to retrieve the ratings, we simply need to replace any reference to the work \"Category\" with the work \"Rating\".\n\n![Advanced Editor](images/pq-02-advanced-editor.png)\n\nPaste the following code:\n\n```\nlet\n    Source = Json.Document(Web.Contents(\"https://YOUR_SEARCHSERVICENAME.search.windows.net/indexes/hotels-sample-index/docs?api-version=2021-04-30-Preview\u0026search=*\u0026facet=Category%2Ccount%3A0\u0026top=0\", [Headers=[#\"api-key\"=\"YOUR_QUERYAPIKEY\"]])),\n    #\"@search facets\" = Source[#\"@search.facets\"],\n    facets = #\"@search facets\"[Category],\n    #\"Converted to Table\" = Table.FromList(facets, Splitter.SplitByNothing(), null, null, ExtraValues.Error),\n    #\"Expanded Column1\" = Table.ExpandRecordColumn(#\"Converted to Table\", \"Column1\", {\"value\"}, {\"Column1.value\"}),\n    #\"Renamed Columns\" = Table.RenameColumns(#\"Expanded Column1\",{{\"Column1.value\", \"Values\"}}),\n    #\"Sorted Rows\" = Table.Sort(#\"Renamed Columns\",{{\"Values\", Order.Ascending}})\nin\n    #\"Sorted Rows\"\n```\n\nUpdate YOUR_SEARCHSERVICENAME to your Azure Cognitive Search service name and update YOUR_QUERYAPIKEY to the Query API Key you created in the above step.\nClick Done and you should see a table that shows all the possible categories.\n\n![Categories Table View](images/pq-03-categories.png)\n\n### Retrieve all Parking Included values\nTo create a query to get all the ParkingIncluded, we will duplicate the previous query and modify it. To do this, right click on \"facetCategories\" and choose \"Duplicate\".\nRight click on the duplicated query and name it facetParkingIncluded.\nRight click on facetParkingIncluded and choose \"Advanced Editor\".\nUpdate the two refereces of \"Category\" to \"ParkingIncluded\".\nClick Done and you should see a table that shows all the possible values for ParkingIncluded (True and False).\n\nClose the Power Query Editor and chooose \"Keep\".\n\nYou should now see two new workbook tabs called \"facetParkingIncluded\" and \"facetCategories\".\n\n![Excel Facet Tabs](images/pq-04-new-facet-tabs.png)\n\n## Name the tables\nWe now need to name the resulting tables that exist within the workbooks so that the search interface we will create later can refer to them. \n\nOpen the facetCategories tab and click on cell A1 and choose Ctrl-F3 to open the Name Manager.\nPress \"New\" and set:\n\n```\nName: categoryTable\nScope: Workbook\nRefers To: =facetCategories!$A:$A\n```\nChoose OK.\n\nNext we will do the same for \"Parking Included\".\nClick \"Add\" and enter:\n\n```\nName: parkingIncludedTable\nScope: Workbook\nRefers To: =facetParkingIncluded!$A:$A\n```\nChoose OK.\n\nClose the Name Manager.\n\n## Create the Search Interface\n\nNow that we have retrieved the facets and names the resulting tables, we will create a workbook that allows us to do full text search and to leverage these facets to refine the search results.\n\nRight click and rename the workbook \"Sheet1\" to \"Search\" and drag it to the left so it is the first workbook of the workbook.\n\n### Create the filters and name them\nIn the \"Search\" workbook add the following text into cells A1, A2 and A3\n\n```\nSearch Query\nCategory\nParking Included\n```\n\nCells B1, B2 and B3 will be used to eithen enter the search query (B1) or choose the filters (B2, B3). The filters will be a drop down box populated with the facet values we previously created queries for.\n\nNext we will name cells B1, B2 and B3 as follows (see below image for where to enter the name). Remember to press ENTER after entering the name for the cell:\n\n```\nsearchQuery\nfilterCategory\nfilterParkingIncluded\n```\n\n![Name Cells](images/search-app-01-filter-names.png)\n\n### Link filters to queries as lists\nNow we will link the cells B2 and B3 to the facet tables so that a drop down list can automatically be populated.\n\nClick on cell B2 and choose \"Data Validation\" under Data -\u003e Data Tools\n\n![Create Drop Down List](images/search-app-01-data-validation-create-list.png)\n\nLink the list by entering:\n\n```\nAllow: List\nSource: =categoryTable\n```\n\nClick OK\n\nTo create the drop down for Parking Included click on cell B3 and choose \"Data Validation\" under Data -\u003e Data Tools\nLink the list by entering:\n\n```\nAllow: List\nSource: =parkingIncludedTable\n```\n\nClick OK and close the Data Validation Window.\n\nMove the mouse to the right of cell B2 and choose the drop down list to verify data is being retrieved. You should notice that the header from the table \"Values\" is being included. We will fix this next.\n\n![Drop Down List Test](images/search-app-03-drop-down-test.png)\n\n### Allowing \"All\" Filter Values\nThere will be cases where you don't actually want to filter results. For example, you might not may not care if parking is or is not included. Since the Parking Included list only has a True and False option, it would be good if we could allow for \"All\" as an option.\n\nLuckily an easy fix for this is to go to the Workbooks facetParkingIncluded and facetCategories and change the Header \"Values\" in cell A1 to \"All\".\n\nOpen workbook facetCategories and update the text of cell A1 from \"Values\" to \"All\"\nOpen workbook facetParkingIncluded and update the text of cell A1 from \"Values\" to \"All\"\n\nGo back to the \"Search\" workbook and verify that \"All\" is an option in the lists.\n\n### Create the Search Query\nWe now have everything we need to execute the actual search query that leverages the search query text and search filters.\n\nCreate a new blank query by choosing Home-\u003eGet Data-\u003eFrom Other Sources-\u003eBlank Query\n\nRight click on the new query and name it postSearchQuery\n\nRight click on postSearchQuery and choose Advanced Editor\n\nEnter the following into the editor\n\n```\nlet\n    url = \"https://YOUR_SEARCHSERVICENAME.search.windows.net/indexes/hotels-sample-index/docs/search?api-version=2021-04-30-Preview\",\n    queryApiKey = \"YOUR_QUERYAPIKEY\",\n    // Create the search string - need an if for case where it is empty\n    searchQueryStr =if Excel.CurrentWorkbook(){[Name=\"searchQuery\"]}[Content]{0}[Column1] \u003c\u003e null then \"\"\"search\"\": \"\"\" \u0026 Excel.CurrentWorkbook(){[Name=\"searchQuery\"]}[Content]{0}[Column1] \u0026 \"\"\"\" else \"\"\"search\"\": \"\"*\"\"\",\n    categoryFilter = if Excel.CurrentWorkbook(){[Name=\"filterCategory\"]}[Content]{0}[Column1] \u003c\u003e \"All\" and Excel.CurrentWorkbook(){[Name=\"filterCategory\"]}[Content]{0}[Column1] \u003c\u003e null then \"\"\"filter\"\": \"\"Category eq '\" \u0026 Excel.CurrentWorkbook(){[Name=\"filterCategory\"]}[Content]{0}[Column1] \u0026 \"'\"\",\" else \"\",\n    parkingIncludedFilter = if Excel.CurrentWorkbook(){[Name=\"filterParkingIncluded\"]}[Content]{0}[Column1] \u003c\u003e \"All\" and Excel.CurrentWorkbook(){[Name=\"filterCategory\"]}[Content]{0}[Column1] \u003c\u003e null then \"\"\"filter\"\": \"\"ParkingIncluded eq '\" \u0026 Excel.CurrentWorkbook(){[Name=\"filterParkingIncluded\"]}[Content]{0}[Column1] \u0026 \"'\"\",\" else \"\",\n    body = \"{\"\"queryType\"\": \"\"simple\"\", \" \u0026 categoryFilter \u0026 parkingIncludedFilter \u0026 searchQueryStr \u0026 \"}\",\n    Source = Json.Document(Web.Contents(url,[Headers = [#\"Content-Type\"=\"application/json\", #\"api-key\"=queryApiKey], Content=Text.ToBinary(body)  ] )),\n    value = Source[value],\n    #\"Converted to Table\" = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error),\n    #\"Expanded Column1\" = Table.ExpandRecordColumn(#\"Converted to Table\", \"Column1\", {\"HotelId\", \"HotelName\", \"Description\", \"Description_fr\", \"Category\", \"Tags\", \"ParkingIncluded\", \"LastRenovationDate\", \"Rating\", \"Location\", \"Address\", \"Rooms\"}, {\"Column1.HotelId\", \"Column1.HotelName\", \"Column1.Description\", \"Column1.Description_fr\", \"Column1.Category\", \"Column1.Tags\", \"Column1.ParkingIncluded\", \"Column1.LastRenovationDate\", \"Column1.Rating\", \"Column1.Location\", \"Column1.Address\", \"Column1.Rooms\"})\nin\n    #\"Expanded Column1\"```\n```\n\nUpdate YOUR_SEARCHSERVICENAME to your Azure Cognitive Search service name and update YOUR_QUERYAPIKEY to the Query API Key you created in the above step.\nClick Done and you should see a table that shows all the possible search results based on the selected filter and text search.\n\nClose the Power Query Editor and Keep the changes.\n\n### Clean up the Search Interface\n\nFrom the last step you should see a table that shows the results of the search query. To make the search interface more usable, we will combine the search results, search query and filters into a single workbook.\n\nRename the workbook \"postSearchQuery\" to \"Search App\"\n\nInsert 4 rows above the search results table.\n\nGo to the \"Search\" workbook and cut cells A1 to B3 into clipboard.\n\nGo to the \"Search App\" workbook and paste the cells at B1.\n\nThe result should look like this:\n\n![Search App Combined](images/search-app-04-combiined.png)\n\nAt this point you should be able to choose a value in the dropdown or enter text into cell C1 for the search query and then choose Data-\u003eRefresh All to execute the query.\n\n### Add a Search Button to Execute Search (Optional)\n\nTo make things simpler, we are going to add a search button that will execute the query to retrieve the data and populate the resulting table. This requires you to save the file as an Macro Enabled Workbook so you may choose to skip this step.\n\nTo create the search button:\n\nSave the file as a Excel Macro Enabled Workbook with a file type of (*.xlsm).\nIn the \"Search App\" workbook, go to cell A1.\nFrom the menu choose Insert -\u003e Icons\nType \"Search\" into the box and choose the icon for your button and press \"Insert\"\nResize and move the icon to where you would like it placed.\nRight click on the icon and choose \"Assign Macro\"\nChoose \"New\" and paste the following code:\n\n```\nSub RefreshSearchResults()\n    ThisWorkbook.Queries(\"postSearchQuery\").Refresh\nEnd Sub\n```\n\nClose the VBA Editor window.\n\nEnter a value into cell C1 for the search text such as \"chic\" and press the search button. You should see the results refreshed. In the event this does not work, try right clicking the image and choose \"Assign Macro\", choose RefreshSearchResults, close the window and try again.\n\n![Search App in Excel](images/search-app-final.png)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliamca%2Fexcel-search-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fliamca%2Fexcel-search-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliamca%2Fexcel-search-app/lists"}