Are you tired of spending hours writing complicated VBA code to locate and manipulate data on your Excel worksheet? Are you concerned that any updates to the sheet might break your code? Look no further! AWE_Sheet is a FREE, open-sourceVBA Class Module that you can add to your Excel workbook. It simplifies finding, retrieving, and manipulating data on your worksheet, reducing pages of tedious code to just a few calls. With AWE_Sheet, you can manually add or move columns and rows of data on your sheet without the need to update your macros. It's the perfect answer for creating efficient business solutions with minimal code. Boost your productivity with AWE_Sheet!
Find Cells
Worksheets - Initialize (open) a Worksheet as ReadOnly or Writable, located anywhere in your network (SharePoint, Teams, hard drive...).
Flexible - AWE_Sheet.FindCells replaces Worksheet.Cells, but with greater functionality. Find one or more Cells by column name, number, or range; and the column's rows by search pattern, number, or range.
Easy - AWE_Sheet takes care of the hard work, allowing you to focus on solving your business problem.
The below macro shows how to declare and initialize AWE_Sheet, locate columns based on their names, and search for cells based on data patterns. The sheet and its column headers are defined during the Initialize call. After that, the FindCells function is utilized to find data ranges by specifying the column name and cell patterns.
PublicFunctionFindCells()DimaweShAsNewAWE_Sheet,rEmpNmAsRange'--- Initialize AWE_Sheet ---
aweSh.InitializeTableOrSheetNmOrObj:="Timecard",HdrRowNb:=3,WBFullFileNmOrObj:=Nothing,WBReadOnly:=False'--- Find Cells by Column Name and a Search pattern: unknown chars (*), hyphen (-), 2 chars (??), ending in 01 ---
ForEachrEmpNmInaweSh.FindCells("*-??01","Employee Name",True)Debug.PrintrEmpNm.Value'--- Use the Employee Name's range to find the row's associated column (TaskID) values ---
Debug.PrintaweSh.FindCells(rEmpNm,"TaskID").ValueNextrEmpNmEndFunction
Filter Rows
Worksheet Extensibility - Use AWE_Sheet in combination with any Worksheet function that uses a range (filters, sum)...
AWE_ColHdr and AWE_ColNbr Retrieve a column's range and number (respectively).
DataColumns - Retrieve one or more data columns (Union together) by column name, number or range.
FindCells - As described above, retrieves a cell's range by column name on the given row.
Dynamic - Use column names and search values allowing you to insert or delete columns and rows with minimal impact to your code.
The below macro combines the power of AWE_Sheet to find column ranges with the Worksheet Function to Filter over a million rows and cells of data in less than a second. Say goodbye to worrying about tedious column numbers and named ranges forever.
PublicFunctionFilterRows()DimaweShAsNewAWE_Sheet,rRateAsRange'--- Initialize the AWE_Sheet ---
aweSh.InitializeTableOrSheetNmOrObj:="Timecard",HdrRowNb:=3'--- Create Filter using an Array ---
aweSh.ColHdr("TaskID").AutoFilterfield:=aweSh.ColNbr("TaskID"),_Criteria1:=Array("Task-127","Task-145"),Operator:=xlFilterValues'--- Add a From and To Date to the Filter ---
aweSh.ColHdr("Date").AutoFilterfield:=aweSh.ColNbr("Date"),Operator:=xlAnd,_Criteria1:=">="&CDate("1/1/2021"),Criteria2:="<="&CDate("12/31/2021")'--- Loop through each found row and calculate\update its revenue ---
ForEachrRateInaweSh.DataColumns("Rate").SpecialCells(xlCellTypeVisible)rRate.Value=227.5aweSh.FindCells(rRate,"Revenue").Value=rRate.Value*aweSh.FindCells(rRate,"Hours").ValueNextrRate'--- Sum Revenue for all filtered rows ---
Debug.PrintWorksheetFunction.Sum(aweSh.DataColumns("Revenue").SpecialCells(xlCellTypeVisible))EndFunction
Function definitions, parameters and examples are included in the comments before each property or function.
Visual Basics Class IntelliSense will provide a code completion aid for the AWE_Sheet Class Module by listing its functions and parameters as you type your code.
Implement AWE_Sheet into your Workbook by copying the below code into a Class Module called, AWE_Sheet. Once implemented, begin simplifying your code so that you can spend more time focusing on solving your business problem.
'*****************************************************************************************************
'* AWE_Sheet: AWE_Sheet include prewritten functions that allow you to find, retrieve, and *
'* manipulate data on your sheet with just a few calls so you can accomplish your *
'* business solution with less code. *
'* Author: Mike Libby *
'* Website: AutomationWithExcel.com *
'*****************************************************************************************************
OptionExplicitPrivatem_WorksheetAsWorksheet'--- The Worksheet object ---
Privatem_HdrRowNbAsLong'--- The column header row number ---
Privatem_HdrArrAsVariant'--- An Array of column header names ---
'----------------------------------------------------------------------------------------------------
' Initialize - Initialize the AWE_Sheet object
' Parameters:
' TableOrSheetNmOrObj as Variant - A Worksheet name (String), Worksheet Object, or Table ListObject
' Optional HdrRowNb as Long - The header's row number. Default = 1
' Optional WB as Workbook - The Worksheet's Workbook Object or FullFileName. Default = ThisWorkbook.
'
' Examples:
' ActiveSheet - Dim AWESh as new AWE_Sheet: AWESh.Initialize ActiveSheet, 3
' Sheet name - Dim AWESh as new AWE_Sheet: AWESh.Initialize "Worksheet Name", 3
' Table Name - Dim AWESh as new AWE_Sheet: AWESh.Initialize ActiveSheet.ListObjects("TableNm")
' Read only Workbook - Dim AWESh as new AWE_Sheet: AWESh.Initialize "ShNm", 3, "FullFileNm", True
'----------------------------------------------------------------------------------------------------
PublicFunctionInitialize(TableOrSheetNmOrObjAsVariant,OptionalHdrRowNbAsLong=1,_OptionalWBFullFileNmOrObjAsVariant=Nothing,_OptionalWBReadOnlyAsBoolean=False)'--- Workbook ---
DimwbAsWorkbookSelectCaseTypeName(WBFullFileNmOrObj)Case"Workbook":Setwb=WBFullFileNmOrObjCase"String":Setwb=Workbooks.Open(Filename:=WBFullFileNmOrObj,ReadOnly:=WBReadOnly)CaseElse:Setwb=ThisWorkbookEndSelect'--- Worksheet ---
Setm_Worksheet=NothingSelectCaseTypeName(TableOrSheetNmOrObj)Case"Worksheet":Setm_Worksheet=TableOrSheetNmOrObjCase"String":Setm_Worksheet=wb.Sheets(CStr(TableOrSheetNmOrObj))Case"ListObject":Setm_Worksheet=TableOrSheetNmOrObj.Parentm_HdrRowNb=TableOrSheetNmOrObj.HeaderRow.RowEndSelect'--- Worksheet not found, Critical Error Msg, Stop Processing ---
Ifm_WorksheetIsNothingThenMsgBox"Invalid Sheet - Ensure the sheet exists within the Workbook",vbCritical:EndEndIf'--- Header Row ---
m_HdrRowNb=HdrRowNbm_HdrArr=HeaderRow.ValueEndFunction'====================================================================================================
' === Properties ====================================================================================
'====================================================================================================
'----------------------------------------------------------------------------------------------------
' HeaderRow - Return the range for the entire header row
' Example: Dim rng As Range: Set rng = AWESh.HeaderRow
'----------------------------------------------------------------------------------------------------
PublicPropertyGetHeaderRow()AsRangeWithm_WorksheetSetHeaderRow=.Range(.Cells(m_HdrRowNb,1),.Cells(m_HdrRowNb,_.Cells(m_HdrRowNb,.Columns.Count).End(xlToLeft).Column))EndWithEndProperty'----------------------------------------------------------------------------------------------------
' LastDataRow - Return the last data row's number
' Example: Dim rng as Range: Set rng = AWESh.LastDataRow.row
'----------------------------------------------------------------------------------------------------
PublicPropertyGetLastDataRow()AsRangeWithm_WorksheetDimiRowAsLong:iRow=.Cells.Find("*",LookAt:=xlPart,LookIn:=xlFormulas,_SearchOrder:=xlByRows,SearchDirection:=xlPrevious).RowIfiRow>m_HdrRowNbThenSetLastDataRow=.Range(.Cells(iRow,1),.Cells(iRow,_.Cells(iRow,.Columns.Count).End(xlToLeft).Column))EndWithEndProperty'----------------------------------------------------------------------------------------------------
' AppendDataRow - Return the range of the the Sheet's LastDataRow + 1
' Example: Dim rng as Range: Set rng = AWESh.AppendDataRow
'----------------------------------------------------------------------------------------------------
PublicPropertyGetAppendDataRow()AsRangeWithm_WorksheetDimiRowAsLong:iRow=.Cells.Find("*",LookAt:=xlPart,LookIn:=xlFormulas,_SearchOrder:=xlByRows,SearchDirection:=xlPrevious).RowIfiRow<m_hdrrowTheniRow=m_HdrRowNbiRow=iRow+1:SetAppendDataRow=.Range(.Cells(iRow,1),.Cells(iRow,_.Cells(iRow,.Columns.Count).End(xlToLeft).Column))EndWithEndProperty'----------------------------------------------------------------------------------------------------
' DataBodyRange - Return the range for all rows under the sheet header or Nothing if none found
' Param: IncludeHeader as Boolean - True if the header should be included; otherwise False (default)
' Example: Dim rng As Range: Set rng = AWESh.DataBodyRange
'----------------------------------------------------------------------------------------------------
PublicPropertyGetDataBodyRange(OptionalIncludeHeaderAsBoolean=False)AsRangeDimiFirstRowAsLong:IfIncludeHeader=TrueTheniFirstRow=m_HdrRowNbElseiFirstRow=m_HdrRowNb+1DimiLastRowAsLong:iLastRow=m_Worksheet.Cells.Find("*",LookAt:=xlPart,LookIn:=xlFormulas,_SearchOrder:=xlByRows,SearchDirection:=xlPrevious).RowIf(IncludeHeader=FalseAndiLastRow=m_HdrRowNb)OriLastRow=-1ThenSetDataBodyRange=Nothing:ExitFunctionEndIfWithm_WorksheetSetDataBodyRange=.Range(.Cells(iFirstRow,1),.Cells(iLastRow,_.Cells(m_HdrRowNb,.Columns.Count).End(xlToLeft).Column))EndWithEndProperty'----------------------------------------------------------------------------------------------------
' Sheet - Returns the worksheet used by AWE_Sheet
' Examples - Dim sh as Worksheet: Set sh = AWESh.Sheet
'----------------------------------------------------------------------------------------------------
PublicPropertyGetSheet()AsWorksheet:SetSheet=m_Worksheet:EndProperty'----------------------------------------------------------------------------------------------------
' Workbook - Returns the Workbook used by AWE_Sheet
' Examples - Dim wb as Workbook: Set wb = AWESh.Workbook
'----------------------------------------------------------------------------------------------------
PublicPropertyGetWorkbook()AsWorkbook:SetWorkbook=m_Worksheet.Parent:EndProperty'====================================================================================================
' === COLUMNS =======================================================================================
'====================================================================================================
'----------------------------------------------------------------------------------------------------
' DataColumns - Return the range for one or more columns based on their column number, name or range.
' Return: one or more column ranges.
' Params: ColNbrOrNameOrRanges as Variant. A list of column numbers, names, or Ranges.
' Example: Dim rng As Range: Set rng = DataColumns("Column 1", "Column 5", "Column 6")
'----------------------------------------------------------------------------------------------------
PublicFunctionDataColumns(ParamArrayColNbrsOrNamesOrRanges()AsVariant)AsRangeDimRtnRngAsRange,VarAsVariantForEachVarInColNbrsOrNamesOrRangesIfRtnRngIsNothingThenSetRtnRng=DataBodyRange.Columns(ColNbr(Var))_Else:SetRtnRng=Union(RtnRng,DataBodyRange.Columns(ColNbr(Var)))NextVarSetDataColumns=RtnRngEndFunction'----------------------------------------------------------------------------------------------------
' ColNbr - Search for and return a Column's number on the header row
' Params: ColNbrOrNameOrRange as Variant. A column number, name, or Range.
' Example: Dim iCol as Long: iCol = AWESh.ColNbr("Column Name")
' Note: a critical message displays if the column is not found and processing stops.
'----------------------------------------------------------------------------------------------------
PublicFunctionColNbr(ColNbrRangeOrNameAsVariant)AsLongDimiColNbrAsLong'--- Column Number ---
OnErrorResumeNextSelectCaseTypeName(ColNbrRangeOrName)Case"Long","Integer":iColNbr=ColNbrRangeOrNameCase"Range":iColNbr=ColNbrRangeOrName.ColumnCase"String":iColNbr=-1:iColNbr=Application.Match(ColNbrRangeOrName,m_HdrArr,0)'--- Try again if column was not found ---
IfiColNbr=-1Thenm_HdrArr=HeaderRow.ValueiColNbr=Application.Match(ColNbrRangeOrName,m_HdrArr,0)EndIfEndSelectOnErrorGoTo0IfiColNbr=-1ThenMsgBox"Critical Error "&m_Worksheet.Name&"::AWE_Sheet::ColNbr"&vbLf&vbLf&_"Cannot find column, """&ColNbrRangeOrName&""".",vbCritical:EndEndIfColNbr=iColNbrEndFunction'----------------------------------------------------------------------------------------------------
' ColHdr - Find and return a column header's cell range.
' Params: ColNbrOrNameOrRange as Variant. A column number, name, or Range.
' Example: Dim rng As Range: set rng = AWESh.ColHdr "Column Name"
'----------------------------------------------------------------------------------------------------
PublicFunctionColHdr(ColNbrOrNameOrRangeAsVariant)AsRangeSetColHdr=m_Worksheet.Cells(m_HdrRowNb,ColNbr(ColNbrOrNameOrRange))EndFunction'====================================================================================================
' === FIND CELLS ====================================================================================
'====================================================================================================
'----------------------------------------------------------------------------------------------------
' FindCells: Search for one or more cell ranges using any combination of a column's and row's number,
' range, or a search value.
' Return: One or more cell ranges that were found in the column.
' Params: RowNbrRangeOrSrchStr - The row number, range, or a string that is being searched for.
' For String Wildcards use: "*" match zero or more unknown characters;
' "?" match any single unknown character in a string;
' "#" match any single digit (0 thru 9) in a string;
' "[charlist]" match any single character in the charlist;
' "[!charlist]" match any single character not in the charlist;
' Note, a hyphen in a charlist separates upper and lower bounds, i.e.
' [a-zA-Z0-9] matches lower and upper case A thru Z and 0 thru 9.
' ColNbrRangeOrName - The column number, range, or name string that contains the row that is
' being searched for.
' SearchAllRows - True if all rows are being searched or false (default) if only the first
' occurrence is to be found. Note, sort order for multiple rows is
' non-contiguous cells first, followed by continuous cells.
' Example:
' Dim rng as Range
' '--- Find cells in column, "Name" that contain a hyphen followed by 4 digits and a character ---
' For Each rng In AWESh.FindCells("*-####?", "Name", True)
' '--- Print each found value and the corresponding row from the "Date" column ---
' Debug.Print rng.Value & " - " & AWESh.FindCells(rng, "Date").Value & " - " & rng.Row
' Next rng
'----------------------------------------------------------------------------------------------------
PublicFunctionFindCells(RowNbrRangeOrSrchStrAsVariant,ColNbrRangeOrNameAsVariant,_OptionalSearchAllRowsAsBoolean=False)AsVariantDimrCellAsRange,rSrchRngAsRange,sFirstAsString,rRtnRngsAsNewCollectionDimiLastRowAsLong,iColNbrAsLong:iColNbr=ColNbr(ColNbrRangeOrName)'--- SearchFor row(s) in iColNbr ---
Withm_WorksheetSelectCaseTypeName(RowNbrRangeOrSrchStr)Case"Long","Integer":SetrCell=.Cells(RowNbrRangeOrSrchStr,iColNbr)Case"Range":SetrCell=.Cells(RowNbrRangeOrSrchStr.Row,iColNbr)Case"String":'--- Get the range of the search column ---
iLastRow=.Cells.Find("*",LookAt:=xlPart,LookIn:=xlFormulas,_SearchOrder:=xlByRows,SearchDirection:=xlPrevious).RowSetrSrchRng=.Range(.Cells(m_HdrRowNb+1,iColNbr),.Cells(iLastRow,iColNbr))'--- Find the first occurance ---
Application.FindFormat.ClearSetrCell=rSrchRng.Find(What:=CStr(RowNbrRangeOrSrchStr),LookIn:=xlValues,_SearchOrder:=xlByRows,SearchDirection:=xlNext,LookAt:=xlWhole)EndSelectIfSearchAllRows=FalseThenSetFindCells=rCell:ExitFunctionEndIfEndWith'--- If SearchAllRows is True and the first row was found then find all occurances ---
IfSearchAllRows=TrueAndTypeName(RowNbrRangeOrSrchStr)="String"ThenIfNotrCellIsNothingThensFirst=rCell.AddressDorRtnRngs.AddrCellSetrCell=rSrchRng.FindNext(rCell)LoopWhilerCell.Address<>sFirstEndIfEndIfSetFindCells=rRtnRngsEndFunction'====================================================================================================
' === SORT and FILTER ===============================================================================
'====================================================================================================
'----------------------------------------------------------------------------------------------------
' SortSheet - Sort the sheet by ascending or descending row values in one or more columns.
' Params: ColIdxOrNames As Variant - Column numbers or names to sort by. Prepend "<" to reverse sort.
' Example: Sort Col1 ascending and Col2 decending - AWESh.Sort "Col1 Name", "<Col2 Name"
'----------------------------------------------------------------------------------------------------
PublicFunctionSortSheet(ParamArrayColIdxOrNames()AsVariant)DimColIdxOrNameAsVariant,ColIdxAsLongWithm_Worksheet.SortForEachColIdxOrNameInColIdxOrNamesIfLeft(ColIdxOrName,1)="<"ThenColIdxOrName=Trim(Right(ColIdxOrName,Len(ColIdxOrName)-1)).SortFields.Addkey:=DataColumns(ColNbr(ColIdxOrName)),Order:=xlDescendingElseIfLeft(ColIdxOrName,1)=">"Then_ColIdxOrName=Trim(Right(ColIdxOrName,Len(ColIdxOrName)-1)).SortFields.Addkey:=DataColumns(ColNbr(ColIdxOrName)),Order:=xlAscendingEndIfNext.SetRangeDataBodyRange:.Header=xlNo:.Apply:.SortFields.ClearEndWithEndFunction'----------------------------------------------------------------------------------------------------
' ClearSheetFilters - Clears all Filters on the Sheet
' Example: AWESh.ClearSheetFilters
' Note: Displays a message and ends processing if the sheet is protected and processing stops.
'----------------------------------------------------------------------------------------------------
PublicFunctionClearSheetFilters()OnErrorResumeNextDimcntAsLong:cnt=m_Worksheet.AutoFilter.Range.Areas.CountIfErr.Number>0ThenHeaderRow.AutoFilterfield:=1,VisibleDropDown:=TrueOnErrorResumeNext'--- Verify that the sheet isn't protected ---
Ifm_Worksheet.ProtectContents=TrueThenMsgBox"Critial Error: "&m_Worksheet.Name&"::ClearSheetFilters"&vbLf&vbLf&_"Unprotect sheet before clearing filters.",vbCritical:EndEndIfIfm_Worksheet.AutoFilter.Range.Areas.Count>0Thenm_Worksheet.ShowAllDataEndFunction