Value in Excel cell - excel

I would like to write a function in Excel that finds the last value in the row and copies the information to a different cell.
i.e last info is on cell row 2 column AX = 'hello', then to copy it to row 2 column F.
Thank you.

This is as simple as selecting your desired cell (F2) and typing =AX2 in the formula bar.
If 'hello' is written in AX2, it will be automatically copied to F2.
I suppose if you wanted to employ a user control and VBA to accomplish this, this code would work.
Dim str as String
str = Range("AX2")
Range("F2") = str
Or even simpler
Range("F2") = Range("AX2")

Related

With openpyxl, nested list starts writing / appending to cell A2 not A1

I have an excel spreadsheet to calculate data that is added every week for comparison on the first sheet and each additional sheet is the raw data listed as W01 to W52 for each week. I've stripped down the code here to make the issue the only thing not working. In reality, I'm taking multiple CSVs and dumping them into a list, formatting the list and then I am trying to write that list into the first unused worksheet.
It is successfully finding the first empty worksheet, but then when it writes the data from the list into it, it is starting at A2 not A1.
So the worksheet already exists. I have tried deleting all the cells and clearing the contents within excel first, but it always starts at A2 not A1. What am I missing?
Note: If this helps, originally, I had just deleted last year's data from the worksheet, and when I left it like this, it would start adding the list's data on the first row after the deleted info, such as A52 or something. Deleting the contents of the sheet has "fixed" that issue so it is now only starting at A2 but I want to start it at A1.
If I manually add something to the A1 cell, it works, such as:
ws_week.cell(row=1, column=1).value = 'This should be A1'
So I think I can force it to write with a loop for the row number in a loop for the column number, but it seems like the below should be working.
import openpyxl
output_excel = 'KB Videos 2021.xlsx' #Excel Report
#opens excel report
wb = openpyxl.load_workbook(output_excel)
#find the first blank worksheet
for sheet in wb.sheetnames:
if sheet == 'Weekly Stats':
pass #ignore first worksheet i.e. calculations
elif wb[sheet]['A1'].value == None:
ws_week = wb[sheet]
break
test=[[1,2,3],['A','B','C'],[4,5,6],['a','b','c']]
for x in test:
ws_week.append(x)
wb.save(output_excel)
print('Populated ',ws_week.value)`enter code here`)
The 1,2,3 from the "test" list are being put into A2, B2, C2 when I expect them to be in A1, B1, C1.
What did I miss?
Worksheets should never really be considered as "blank". When appending to worksheets, openpyxl uses an internal counter that will start at the next below any existing cells. As openpyxl creates cells on demand, wb[sheet]['A1'].value will implicitly create the cell "A1" so that it can check the value. This is why data is subsequently appended from the second row. You can avoid this by deleting the row after the check, but you might also want to make the check a little more robust.
Here's the code I used to make it work:
I replaced:
for x in test:
ws_week.append(x)
with:
# calculate max rows and columns
maxr = len(test)
maxc = len(test[0]) #I could probably put this into the loop in case a column is different, but not with my data
for this_row in range (1, maxr + 1):
for this_column in range (1, maxc + 1):
cellsource = test[this_row-1][this_column-1]
ws_week.cell(row = this_row, column = this_column).value = cellsource

combine all cells, numbers and symbols to a sum

Good day,
I'm at a loss on this problem.
I have a group of cells that contain words, like apple, this word would be the value. It is separated by a symbol for completing the math. They can be changed by the user to make custom calculations.
Cell A1 is "apple", B1 is "+", cell C1 is "apple", cell D1 is "*", cell E1 is "apple", call F1 is "=" and cell G1 is the suggested total, in this case would be "6".
It would be posted as | apple | + | apple | * | apple | = | 6 |
The legend holds the value for the word, so if you enter 2 in the legend, apple would be 2.
The logic would determine that the formula would be 2+2*2= if written in excel, I would like to combine all the cells and calculate this.
I tried using =sum, sumproduct, concate and the like to no avail.
Any head way I did make, I ended up getting BEDMAS wrong as it calculated it as 2+2=4*2=8, instead of the correct 2*2=4+2=6.
Anyone know of a way to combine these cells and properly sum the values to the correct total?
Thank you for your time!
Go to the Name manager and create named range Eval, into Refers to field add formula:
=EVALUATE(CONCATENATE(VLOOKUP(Sheet1!A1,Sheet1!$A$3:$B$5,2,0),Sheet1!B1,VLOOKUP(Sheet1!C1,Sheet1!$A$3:$B$5,2,0),Sheet1!D1,VLOOKUP(Sheet1!E1,Sheet1!$A$3:$B$5,2,0)))
In range A3:B5 I have legend.
Change references as you need. Then in cell G1 write formula =Eval.
Sample:
This is a UDF based solution. Its advantage is that it's more versatile and by far easier to maintain if you learn its elements of code. The disadvantage is in that you do have to learn the elements of code and you have an xlsm macro-enabled workbook which isn't welcome everywhere.
The setup is simple. I created a table with columns Item and Value. I placed it on another sheet than the task. In fact, you could make the sheet with the table VeryHidden so that the user can't look at it without access to the VBA project, which you can password protect. I called the table Legend. The item columns has names like apple, pear, orange. The Value column has the numeric values associated with each name.
Note that, since this is a VBA project, the entire list can be transferred to VBA leaving no trace on the sheet. You could have a function to display the value of each item as the user clicks on it and have it disappear as he clicks elsewhere.
Next I created a data validation drop-down in A1 with the List defined as =INDIRECT("Legend[Item]"). Copy this cell to C1 and E1.
Then I created another Data Validation drop-down in B1 with the list as +,-,*,/. This drop-down must be copied to D1.
Now the code below goes into a standard code module. Find the way to create it because it isn't any of those Excel sets up automatically. It's default name would be Module1. Paste the code there.
Function Evalue(Definition As Range) As Double
Dim Task As String
Dim Fact(2) As Double
Dim C As Long
Dim i As Long
With Definition
For C = 1 To 5 Step 2
On Error Resume Next
Fact(i) = Application.VLookup(.Cells(C).Value, Range("Legend"), 2, False)
i = i + 1
Next C
Task = "(" & Fact(0) & .Cells(2).Value _
& Fact(1) & ")" & .Cells(4).Value _
& Fact(2)
End With
Evalue = Evaluate(Task)
End Function
Now you are ready for testing. Call the function from the worksheet with a call like
=Evalue(A1:E1). You can use it in comparisons like =IF(G6 = Evalue(A1:E1), "Baravo!", "Try again"). As you change any of the components the cell with the function will change.
Remember to use absolute addressing if you copy formulas containing the range. If you need to get a result in VBA while testing, use this sub to call the function.
Private Sub TestEvalue()
Debug.Print Evalue(Range("A1:E1"))
End Sub
My Sheet
Here is what I have.
In cells M - U, i count all the instances of the word from cells E, G and I from the legend.
=SUMPRODUCT((LEN(E3)-LEN(SUBSTITUTE(E3,$B$3,"")))/LEN($B$3))
In cells W - AE, I multiply the instances with the value to give me a total each time the word appears.
=SUM(M3*$C$3)
In cell E8 - I8, i add the three possible values together.
=SUM(W3:Y3) so each worded cell is now a number.
I'd like to take the cells E8 - I8 to make a calculation in k8 and so on.
So, each cell is put together to make an
=SUM(E8:I8)
statement, which all works except E11 - I11 which equates to 26 instead of 43.

How to sum data from two ranges if another range contains particular text

I have two lists in excel and each of them contains a column of text + another column with points assigned to it. It looks something like that:
As you can see both text and points can change.
Additionally, I would like to add more lists to it (marked C, D, etc.)
On another sheet, I would like to prepare a summary that calculates the sum of the points assigned to text. I will a summary list with text entries:
and I am looking for a formula which will give me sum of the points from all lists IF text from Summary cell matches any text from any list on previous sheet. The end results for these two lists will look like that:
I tried some SUMIF variations but never got what I wanted. Can someone help me find correct formula?
Here is a more general case.
Say Sheet1 has many arbitrary data sets between column A and column Z like:
First put the following User Defined Function in a standard module:
Public Function Gsum(rng As Range, patrn As String) As Long
Dim r As Range
Gsum = 0
For Each r In rng
If r.Text = patrn Then
Gsum = Gsum + r.Offset(0, 1)
End If
Next r
End Function
Put the data abc in Sheet2 cell B2 and in Sheet2 cell C2 enter:
=gsUM(Sheet1!A1:Z27,B2)
You have to take all the range, like that :
French Version = =SOMME.SI($A$2:$C$5;A8;$B$2:$D$5)
English Version = =Sumif($A$2:$C$5,A8,$B$2:$D$5)
Assuming your data is on sheet1 starting in A1 and the second sheet also starts in A1 on that sheet, put this in B2 and copy down:
=SUMIF(Sheet1!A:C,A2,Sheet1!B:D)
Try this and see if it works. I would test it but I am away from my desk at the moment.
Note, that this formula should be placed on a separate worksheet (just in case).
Sheet2!B2 = SUMPRODUCT(--(Sheet1!$A$1:$AZ$100=Sheet2!$A1), OFFSET(Sheet1!$A$1:$A$Z100,0,1))
Sheet1!A:AZ100 = The Range in which the data is contained
Sheet2!$A1 = The Cell that contains the criteria
You could of course use Friendly names for the ranges if you wish.

How can I get the length of the longest string in a column (Excel)?

I have an Excel spreadsheet that I am writing out to a file. I am currently using the following method to reproduce the contents of each cell:
cell_contents = Right(Space(10) & Trim(Cells(iRow, iColumn)), 10)
However, if the contents of the cell are longer than 10 characters long (or however long I choose to specify), then I loose parts of the data. Is there a way to quickly and easily get the length of the longest string in a range of cells?
I have seen people suggest using the following loop, but I was hoping that I might be able to do it without having to loop over all the cells:
For Each c In SourceRange.Cells
if len(c) > b then b = len(c)
Next c
Record these steps as a macro in the cell you want to calculate the max length.
1) enter this formula
=MAX(LEN(A1:A4), 1) -- Edit for your range.
2) press control-shift enter (FormulaArray)
3) now stop recording macro
4) view the VBA. copy what you need to your VBA.
Should give you something like this:
Selection.FormulaArray = "=MAX(LEN(R[-10]C[1]:R[-1]C[1]))"
Press Alt-F11, insert new module, paste code bellow.
Public Function maxRangeLength(data As Range) As Integer
Dim ret As Integer
ret = 0
For Each cell In data
ret = Application.Max(ret, Len(cell))
Next cell
maxRangeLength = ret
End Function
Usage:
=maxRangeLength(A8:D11)
Could just use ... {=MAX(LEN(A2:A200))}
In the top cell put =MAX(LEN(A2:A200)) .. and then press CTRL-SHIFT-ENTER to get the curly braces.
Suppose that the data is in column A and there is a heading row for your spreadsheet.
Create a new column next to it and enter in the formula: =LEN(A2)
Autofill down that formula.
Turn on filtering for that column and the click the drop-down box on the column heading cell.
Scroll down to the bottom of the list where the largest summarized value is.
That will be the largest value in the column.

Excel conditional formatting for the entire row with more than one formula

After 3 hours of searching I still didn't find an answer, here is what I am trying to do:
I am trying to fill with green any row that has WBS in it and with Red any row that has ACT in it and Blue any row that has EPR in it. It works for the first formula then when I try to add the second one every thing get messed up.
what i have understood is that you need to search a keyword in a row and if its found in any cell of that row then color it.
May be we can do it with conditional formatting but i have another idea. We can create a simple search function in Excel VBA. Something like this:
=search_row(A1:F1,"EPR")
The function will return 1 if EPR is found in any cell of specified row. Now if you create two different columns at the end of data columns, name first with WPS and second with EPR and write this function in it. Like
G1 =search_row(A1:F1,"WPS")
H1 =search_row(A1:F1,"EPR")
Drag it to end. Now sort the columns. First for WPS from higher to lower. Then color all rows having 1 in a single select. Similarly do the same with EPR (H1) column.
To use this function you can download the macro file from the following URL:
http://asimishaq.com/myfiles/SearchHighlight.xlsm
Now to run it first of all enable macros, and then re-open your data file and then open this macro file. As long as this macro file is opened you can use this function. Following is the VBA code if you want to create the macro yourself:
Function search_row(sRow As Range, Keyword As String)
Dim i As Integer
Dim Found As Integer
For i = 1 To sRow.Columns.Count
If InStr(1, LCase(sRow.Cells(1, i)), LCase(Keyword)) > 0 Then
search_row = 1
End If
Next
End Function
I had a go at making a function similar to asim-ishaq to determine if your search term exists in the row for fun :) then tried to apply it to highlighting rows, turns out I dont know how to use conditional formatting very well! Figured it out in the end, hopefully I've explained it well enough.
With this you will have to have (one) extra column at the end of your data to contain the result.
It might be possible to not require the extra column by putting the function inside the conditional formatting, however I couldn't get it to work (didn't try very hard). This isn't a great loss as it's much simpler to edit the formula if its on the workbook, instead of having to go through each conditional rule to edit it, should you need to edit it in the future.
To get the formatting to work you will need to create a number of rules (one per keyword)
You want to create a rule of the type shown below, in the formula box you need something along the lines of: =INDIRECT("D" & ROW())=0 where D is the column containing the result of the function below and 0 is the index of the keyword you're highlighting.
In my example, the formula in the D Column is: =SearchRow(An:Cn,"ABS","KBS","JBS") (where n is the row the formula is on)
Set the formatting as desired then press OK, when you return to the rule manager you will need to update the Applies to value, which should be a range that covers all the data you want to highlight. In my example it was $A$1:$C$3
My function below takes 2+ Arguments, The first is the range to search. The second (and any subsequent ones) are search terms.
The function will return a number. -1 for no matches and 0+ for the found search term. The number depends on the position in the arguments.
A1 = "ABS"
B1 = "SBA"
A2 = "SBA"
B2 = "ABS"
A3 = ""
B3 = ""
C1 = "=SearchRow(A1:B1, "ABS", "SBA")"
C2 = "=SearchRow(A2:B2, "ABS", "SBA")"
C3 = "=SearchRow(A3:B3, "ABS", "SBA")"
C1 > 0
C2 > 1
C3 > -1
The function will always return the first result, searching left to right comparing each cell to the Keywords in order. Using my example, if a cell contained "SBA ABS" the result would be 0 (for ABS). I guess your cells will probably only contain one keyword though so this shouldn't be a problem?
Public Function SearchRow(ByVal Row As Range, ParamArray Keyword() As Variant) As Integer
Dim Column As Integer
Dim Value As String
Dim Index As Integer
Dim Result As Integer
For Column = 1 To Row.Columns.Count
Value = LCase(Row.Cells(1, Column))
Result = -1
For Index = LBound(Keyword) To UBound(Keyword)
If InStr(1, Value, LCase(Keyword(Index))) > 0 Then
Result = Index
Exit For
End If
Next Index
If Result > -1 Then
Exit For
End If
Next Column
SearchRow = Result
End Function

Resources