I want to create a script to make a table to summarise which customer has spend the most money in my store. I have a database with unique names in column A, values in column H and other different data.
The core of the script should work like this:
Search for unique name
Sum all the cells from "KWOTA" column (H column)
Paste name and sum of range into the other sheet.
The problem is, I don't know which way should I take. I planned to search row by row for the names through Do Until...Loop method and - if the name is repeating - add corresponding value to a range. The problem is, it will be necessary to create multiple ranges, one for each name (I don't know how many unique names I have in database) and manipulate with them. I really wish to avoid 'Add to range" method.
Is there a possibility to do it in one script, without help of another worksheet to list all the unique names first?
You could consider using the Find and FindNext methods to locate the unique names and add the value from the H column until all the unique names have been found.
Hope I interpreted your question correctly.
Example format:
Sub Find()
Dim longSum As Long
Dim SearchRange As Range
Dim CellWithUniqueName As Range
Dim FirstUniqueCell As String
Worksheets("Sheet1").Activate
Set SearchRange = Range("A1", Range("A1").End(xlDown))
Set CellWithUniqueName = SearchRange.Find(What:="uniquename")
FirstUniqueCell = CellWithUniqueName.Address
Do
Set CellWithUniqueName = SearchRange.FindNext(CellWithUniqueName)
longSum = longSum + CellWithUniqueName.Offset(0, 7).Value
Loop While CellWithUniqueName.Address <> FirstUniqueCell
'whatever else for pasting etc
End Sub
Related
I have data (names) spread out in a sheet in Excel. It is in columns A through M.
Some rows have data in every column (A-M), some rows have nothing.
I want to extract a list of every unique value (or even a list of every value, and then I can remove duplicates) in the range.
For the life of me, I cannot figure out how to do this and haven't found an example online that pulls unique values from a RANGE, and not a single column.
Any ideas? Let me know if you need a screenshot of the data for more context.
Give this macro a try:
Sub MAINevent()
Dim it As Range, r As Range, x0
With CreateObject("scripting.dictionary")
For Each it In Range("A:M").SpecialCells(2)
x0 = .Item(it.Value)
Next
Set r = Cells(1, "N").Resize(.Count, 1)
r.Value = Application.Transpose(.Keys)
End With
End Sub
You can use Go to Special (Ctrl+G -> Special) to select blanks and remove them (Ctrl+- with cells selected). Then use the formula described here to stack all your columns in one, on top of each other. Then replace formulas with values and finally, use Remove Duplicates.
I want to write a formula like =SUM(tab2!A:A) but instead use the column title of A which is say "count". How can I modify this to look more like: =SUM(tab2!"count")?
The reason I want to do this is because I copy and paste a spreadsheet from another source in tab2 and the column referring to "count" may be in a different column. I want the formula to give me the correct calculation as soon as I paste the new spreadsheet by automatically finding the column to sum up by title name.
I must be missing something because this seems like a very basic question and I can't find the answer anywhere...
Thanks for your help!
I like the idea of naming ranges proposed by #Doug, but if the issue is that you are dumping your data in [and you don't know in advance which column is going to be where] and would need to rename your range every time, there are other options - I suggest using OFFSET. OFFSET allows you to dynamically create a range, starting at a particular point and moving down/up / right/left for as many rows and columns as you determine.
In your case, you will need to combine that with a method for searching the columns to see which one says "Count". I am assuming that your column headings are always in row 1. If they aren't [or if they aren't always in row 2, or any row you know in advance]... you can get around that but then I'd recommend you try to make your data more uniform instead of creating unnecessary Excel workarounds.
In total your formula would look like this:
=SUM(OFFSET(A1,,MATCH("Count",1:1,0)-1,ROWS(A:A),1))
What this does is first determine which column the word "Count" is found in, in row 1. Then it subtracts 1 from that number - this now equals the number of columns to the right that it is, from column A. It uses offset to create a reference to that column, for all rows, and sums those rows together.
Check out the name manager for naming ranges :)
You didn't say whether you would consider a macro solution. If so, this may work.
If the sheet you are pasting into is Sheet2 and the sheet you want the result in is Sheet1, then this macro, if placed in the Worksheet_Activate event of Sheet1 will give you the result as soon as you click on the Sheet1 tab afetr pasting your data into Sheet2:
Private Sub Worksheet_Activate()
Dim r As Range
Dim rCol As Range
Dim rFound As Range
Dim ws As Worksheet
Dim lTotal As Long
Set ws = Sheet2
Set r = ws.Cells
Set rFound = r.Find("count")
If Not rFound Is Nothing Then
Set rCol = rFound.EntireColumn
lTotal = Application.WorksheetFunction.Sum(rCol)
End If
Cells(1, 1) = lTotal
End Sub
It does assume there is only one cell with the word "count" in it on Sheet2.
This question stems off another post I had. (see Search through column in excel for specific strings where the string is random in each cell)
Using the above image as reference, I am trying to search through column B (actually over 1000 lines) using column E as the "lookup values." The end goal would be for "just" the names to be displayed in column C. The trick is all the randomly generated characters the encompass the names. Below is what I would want the datasheet to look like. A formula or module should work, but the vlookup and other lookup function I can't get to work.
For a worksheet function approach, you could enter in C3 and fill down this formula:
=LOOKUP(8^5,SEARCH(E$3:E$7,B3),E$3:E$7)
The constant 8^5=32768 is chosen to be larger than the maximum possible string length so that LOOKUP returns the last matching value. The formula returns #N/A if no string is found.
Another possibility, which may be easier to understand then assylias post initially, but also may be a bit more time consumptive (although with 1,000 rows, I don't think it will matter much) is below.
This requires that you name the range in column E as myNames (or whatever name you wish, just update the code - alternatively, you cuold just write Range("E1:E6")). Also, if you move the random values from column B, update that in the code as well.
Sub findString()
Dim celString As Range, rngString As Range, celSearch As Range, rngSearch As Range
Dim wks As Worksheet
Set wks = Sheets("Sheet1") 'change sheet reference to whatever your sheet name is
Set rngString = wks.Range("myNames")
Set rngSearch = Intersect(wks.UsedRange, wks.Range("B1").EntireColumn)
For Each celString In rngString
For Each celSearch In rngSearch
If InStr(1, celSearch.Text, celString.Value) > 0 Then
celSearch.Offset(, 1) = celString.Value
End If
Next
Next
End Sub
Since, I worked on your original question as well, I would suggest getting the counts through Siddharth's answer and then running this, or assylias's code above to get the names next to the columns. You could put a button the sheet, or just use the Macro dialog box to run the macro.
I must be having a brain fog at this point because I am certain this is easy to do, and in fact I have managed to create other functions that are a bit more complicated for this project.
Anyway, what I am trying to do. I have a sheet (inventory-data) and in column 1, it lists a company name, which is a same for all the rows. i.e. each of the 1900 or so rows have companyname in the first cell.
Now, while the data will always be the same at each application, the number of rows will change.
So, I need a function that will first determine what the last row of data is in the range, and then change all of the cells in column one of each record to name_company. The company names will always be the same so I can staticly assign them. Here is what I have that does not work.
I was able to get it to work another way, but it would replace text all the way down to the very last row of the worksheet, way beyond where the data stops.
Thanks!
Sub changeCompany() 'Changes company name as pulled from Agemni into proper ETA format
Dim myCell As Range
Dim RngToChange As Range 'The range of cells that need to be changed
Dim LastRow As Long 'Declare variable to help determine the last row on a variable length worksheet
Dim i As Integer
With Worksheets("inventory-data") 'set the range to change
Set RngToChange = .Columns(1)
End With
LastRow = Worksheets("inventory-data").UsedRange.Rows.Count 'Have Excel determine what the last row is.
For i = LastRow To 1 Step -1
RngToChange.Cells.Value = "name_company"
Next i
End Sub
I've always had more success with [SomeCellOrRange].CurrentRegion.Rows.Count e.g:
Range("A1").CurrentRegion.Rows.Count
UsedRange looks for any use of cells, not limited to a continuous tabular block. It also sometimes needs you to re-save the workbook before it will properly shrink after you have eliminated some rows.
I'd like to search a description cell for ANY words (criteria) from a predefined list, and pull the relevant dollar amount for the item from the adjacent cell.
To illustrate, here is my setup:
A | B | C | D | E | F |
Date | Descr.| Amount| Cat1 | Cat2 | Cat3 |
D,E,F: Each one of these are item categories. If the item in that row belongs to a category, I would like its amount to populate that category cell in that same row. Each category cell has a formula to test for this and perform the operation.
My first thought was to use VLookup, but I have a list of lookup values. I haven't been able to successfully do that. Each of the category cells has a formula like this -->
=IF(SUM(COUNTIF($B10,{"*costco*","*saputo*","*t & t*"}))>0,$C10," ")
Column B refers to the description, which is searched for any of the criteria. If any of the words are contained in the description, the cell is filled with the amount from column C, otherwise its left with a space.
This works perfectly as is, however I need the criteria (costco, saputo, t&t in this case) to be flexible (add or remove strings to the list) rather than hard-coded in the formula. This is my issue: the formula stops working if I replace the criteria with a reference to another cell. I'm relatively new to excel and not familiar with restrictions/constraints of its functions, which I suspect is the issue.
Any help is much appreciated, let me know if I need to provide more info.
Ankit
Create a Name (like a named range, but refers to a value rather than a range.)
For Excel 2007 and 2010, on the Formulas tab, Defined Names group, Name Manager
For Excel 2003 Insert, Names, Define
Create a new Name (lets use the name "KeyWords") , set it "Refers To" value to
={"*costco*","*saputo*","*t & t*"}
Formula then becomes EDIT enter as an array formula
=IF(SUM(COUNTIF($B10,KeyWords))>0,$C10," ")
Editing the list then becomes editing the value of KeyWords refers to value. This can be done through the Name Manager, or if you wish, through VBA
EDIT
Sample VBA
Sub SetKeyWords()
Dim wb As Workbook
Dim nm As Name
Set wb = ActiveWorkbook
Set nm = wb.Names("KeyWords")
nm.RefersTo = "={""NewString""}"
End Sub
Load the strings you are seeking into an array (via converting a range into an array, or having the user select the strings from a small form you design)
Sub MyLookup(arrCategories() As Variant)
Dim searchrange As Range
Dim xCell As Range
Dim count As Integer
'set searchrange to the proper column
For Each xCell In searchrange
For Each catg In arrCategories
If xCell = catg Then
'Do something here
End If
Next catg
Next xCell
End Sub
You may need to adjust your string array based on whether case matters. Depending on the size of your set of data, it might be better to convert searchrange into an array.
There may be a faster way to see if certain strings are found within a given range, but this is the general idea.