Batch cells update with pygsheets - python-3.x

How can I update spreadsheet range with a list of values?
For example if I have range A1:C7 and I want 1, 2, 3, 4, ... 21 values in cells.
I can't even get a cell list with sheet.range function.
cell_list = sh.range('A1:C7', returnas='cells')
cause it does not return cell object if spreadsheet has empty cells.

To update a range of cells you can use a 2d list
wks.update_cells('A2:C7',[[1,2,3],[4,5,6],[7,8,9] ... etc ])
to get cell objects even if you have empty cells, use
get_values('A1', 'C7', returnas='cells', include_all=True)
sheet.range currently dosen't return the exact rectangle specified (sticking to the api v4). Try raising an issue in github to get it fixed.

Related

Is there a Excel Formula for auto filling a price when certain option of choices is picked?

I am working in Excel. I am trying to come up with a formula that is linked to a drop down menu of choices. I have attached an image below that shows a 'Status' column and 'Double Handling' column. My end goal is when you click a status option the corresponding price gets autofilled in the double handling column.
For example Status :Price
Unchecked :$400,
Checked :$600,
Laydown :$200,
in SWO :$200,
Progress :$200,
Paint :$200,
Laydown :$200,
Site :$200,
If you have your Drop Down options on another tab (a Lookup Sheet), then you can put the Price next to them, and use a VLOOKUP
=VLOOKUP(A1,LookupSheet!$A:$B, 2, FALSE)
This also lets you use a Named Range in your Drop-Downs, so that you just have to add or remove items to the Lookup Sheet, and it will automatically update all of your options. The Named Range would need to contain a Function that used INDEX to set the range, like this:
=LookupSheet!$A$1:INDEX(LookupSheet!$A:$A, MAX(COUNTA(LookupSheet!$A:$A), 1))
(If your Lookup Sheet includes a Header Row, then you will probably want to change $A$1 to $A$2, and that final , 1)) to , 2)) instead)
If you don't want to use a Lookup Sheet, you can include the Lookup Table in the function as an array:
=VLOOKUP(A1, {"Unchecked",400;"Checked",600;"Laydown",200;"in SWO",200;"Progress",200;"Paint",200;"Laydown",200;"Site",200}, 2, FALSE)
The whole array goes inside braces (curly brackets, {}), values on the same Row are separated with Commas ({Input,Output}), and Rows are separated with Semicolons ({Input1,Output1;Input2,Output2})
Though it may seem a bit lenghty, if for whatever reason you want to change up amount, I believe you could nicely implement CHOOSE here:
=CHOOSE(MATCH(A1,{"Unchecked Drawing","Checked Drawing","in SWO","Progress Assign LamSar Shop","Progress Assign Subcontractor","Paint","Laydown","Site"},0),400,600,200,200,200,200,200,200)
Range A1 in my formula refers to the cell with the drop-down. Also, when empty, there will be an error (since MATCH cannot find a match). You could counter that with wrapping the formula in an IFERROR(.....,"").

returning results from a function to cells with offset

I'm learning and writing Excel VBA functions for my needs, and I'm stuck (pretty sure its easy, but I couldn't figure out the error, as excel only returns #VALUE as an error message)
I have written a vba function to return some data, and all is fine until the end. I have the results in a collection (chosen) but I cannot make the function write the results to cells in the same row. ı'm trying to use the range.offset within a for loop:
For t = 1 To chosen.Count
Application.Caller.Offset(0, t).Value = chosen(t)
Next t
so for 1, I want the value from chosen(1) to be returned to the cell on the right, same row. then for 2, it will go the the second cell on the right etc.
A UDF or User Defined Function used as a formula cannot effect the value of another cell.
Now if you want to put an array of values in a range then you simply select the cells for the output and confirm with Ctrl-Shift-Enter.
Using this function that returns an array:
Function myArr() As Variant()
myArr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
End Function
I select A1:I1 with A1 active.
Then I enter
=myArr()
in the formula bar and hit Ctrl-Shift-Enter instead of Enter. Excel will put the formula in all nine cells and put {} around the formulas. The array will then be put in those nine cells.

problems defining a sub range with INDEX formula

My understanding is that you can define a range using index. example I can set a defined name of MyList to
=index(A:A,3,1):index(A:A,5,1)
This would be the equivalent of saying A3:A5. I can then turn around and use index(MyList,1,1) and I would see the contents of A3. All this works for me.
So I was trying to define a range of sheet names. I used defined name sheetnames as:
=TRANSPOSE(GET.WORKBOOK(1,Structural!$J$3)&T(NOW()))
(I used transpose to get the list vertical)
when I use:
=INDEX(Sheetnames,3,1)
=INDEX(Sheetnames,6,1)
I get the name of my 3rd or 6th sheet in my workbook respectively. So that part is working. However when I try to define a range like I did for MyList using the following I get #value
=INDEX(INDEX(Sheetnames,3,1):INDEX(Sheetnames,6,1),1,1)
QUESTION:
Why is it not working?
As a test to get first sheetname I have also tried:
=OFFSET(Sheetnames,1,1,1,1)
This also gave the same error.
What I am ultimately trying to do is generate a pull down list through data validation of all sheet names except the sheets named "Index" and "Master".
As per Excel's help file on INDEX...
Reference form
Description
Returns the reference of the cell at the intersection of a particular
row and column. If the reference is made up of nonadjacent selections,
you can pick the selection to look in.
Syntax
INDEX(reference, row_num, [column_num], [area_num])
The INDEX function syntax has the following arguments.
Reference Required. A reference to one or more cell ranges
etc...
Therefore, in order to return a reference, you would need to reference a range of cells. SheetNames, however, doesn't refer to a range of cells. It refers to GET.WORKBOOK, which returns an array of values. In this case, it returns an array of sheet names.
So with the following formula...
=INDEX(INDEX(Sheetnames,3,1):INDEX(Sheetnames,6,1),1,1)
...it gets evaluated as follows (assuming the workbook is called Book1.xlsx and you have Sheet1, Sheet2, Sheet3, etc)...
--> some preliminary evaluations <---
=INDEX("[Book1.xlsx]Sheet3":"[Book1.xlsx]Sheet6",1,1)
=INDEX(#VALUE!,1,1)
=#VALUE!
You can evaluate the formula for yourself by selecting the cell containing the formula, and stepping through it using the Evaluate Formula button on the Ribbon (Formulas tab > Formula Auditing group).
You can also confirm that INDEX doesn't return a reference in this case by using the ISREF function. The following formula should return FALSE...
=ISREF(INDEX(Sheetnames,3,1))
Hope this helps!

Put unique distinct values into a list from multiple columns of an array

I'm new to Excel and the journey has been good so far, but I haven't been able to resolve this particular issue by myself. I'm dealing with a table as under:
Essentially, I'm looking to refer to the array of tags in columns from B3:E6, and do the following:
Create a "Unique Tags" column: Create a unique list of "tags" in column H by removing duplicates.
Create a "Maximum Marks" column: Look for each of the unique tags in the array in each row, and return the marks from the marks column in the same row. If the tag appears in multiple rows. the sum of the corresponding marks in these multiple rows should be returned in the maximum marks column in column I. For example, 'EASY' appears in E3 as well as E5. Thus in the 'Unique Tags' List 'EASY' should correspond to Maximum Marks = 4 (2+2).
I could do this manually using formulas such as SUMIF, but I'm looking for a way to automate it since I might have to do this operation for a similar dataset with additional rows & columns. I'm open to VBA solutions as well but would prefer some sort of formula.
I hope I've explained it well enough! Thanks and looking forward to your inputs.
One way to do this is create a function that returns the array of your unique cells and then multiplies them all by matches in your Marks column.
Create the unique cells with this array function. Note this function uses the Dictionary object. In the VB Editor, go to Tools > References, and make sure Microsoft Scripting Runtime is selected.
Public Function UniqueValues(aRange As Range)
Dim DictValues As New Dictionary
Dim cll As Variant
Dim aryResults() As String
For Each cll In aRange
If Not DictValues.Exists(cll.Value) Then DictValues.Add cll.Value, "":
Next
UniqueValues = DictValues.Keys
Set DictValues = Nothing
End Function
Enter in cell H3 and press CTRL SHIFT RETURN (as it's an array function)
=TRANSPOSE(uniquevalues(B3:E6))
and drag down to H15 or beyond
We have to use TRANSPOSE as the array comes out in a row from the function.
Next we need to find the matching cells and multiply. Here in C15 enter the formula below
=INDEX(SUM((($B$3:$E$6=H3)*1)*$F$3:$F$6),1)
Drag this down to H15.

How to assign array of values to Excel cells without losing table formatting in VSTO

This may be an easy one, but it escapes me at the moment. I have reworded the question based on some new findings.
I use 2D arrays of values extensively in Excel add-ins for the raw speed increase that gives.
I use extension methods to extract a cell array and modify it, then put the values back.
e.g.:
// Get all cells in the worksheet - this is a formatted table including headings
Range range = worksheet.UsedRange;
// Get all values as a 2D array
object[,] cells = range.GetCellArray();
... // do things to the array
// Assign the entire array back to worksheet, but table formatting is erased
Range.Value = cells;
the table formatting only gets removed by the array assignment. This goes as far as the named table ListObject entry being removed.
Is there a way to keep the table formatting?
There's probably a better way, but my first thought was to output the array to a temporary sheet, then copy the output and Paste Special -> Values only onto your desired range. Finally, delete the temporary sheet.
It turns out that if you replace the cells of the heading row, of a formatted table, you lose the table completely.
The solution is to replace only the rows under the heading.
// Get all cells in the worksheet - this is a formatted table including headings
Range range = worksheet.UsedRange;
// Get all values as a 2D array
object[,] cells = range.GetCellArray();
... // do things to the array
// Assign the entire array MINUS THE HEADING ROW, back to worksheet
cells = cells.SubArray(2, 1, cells.RowCount() - 1, cells.ColumnCount());
EXCEL.Range targetRange = worksheet.GetRange(1, 2, cells.ColumnCount(), cells.RowCount());
targetRange.Value = cells;
The SubArray, GetRange, RowCount and ColumnCount methods are all extension methods I created previously, but you get the idea what they do from their names and the example.

Resources