Python - find cell reference within merged_cells collection in openpyxl - openpyxl

I wish to identify if a cell in a worksheet is found within the merged_cells collection returned by openpyxl.
The merged_cells range looks like this (VSCode debugger):
I have the cell reference J31 - which is found in this collection. How would I write a function that returns true if that cell is found in the merged_cells.ranges collection?

for cell in ^^merged_range^^:
if cell==your_special_cell:
return True
^^merged_range^^ must be of type openpyxl.worksheet.cell_range

Further to D.Banakh's answer (+1), try something like this (building upon a previous example I wrote for someone else, since there is little context to your question):
for cell in ws.merged_cells.ranges:
#print(cellRef +' ==> '+ str(cell.min_row) +'/'+ str(cell.max_row) +'/'+ str(cell.min_col) +'/'+ str(cell.max_col))
if (int(cell.min_row) <= int(row) <= int(cell.max_row)) and (int(cell.min_col) <= int(col) <= int(cell.max_col)):
print('Cell ' +cellRef+ ' is a merged cell')
Example within a context:
import re
cellBorders = fnGetCellBorders(ws, cellRef)
if ('T' in cellBorders) or ('L' in cellBorders) or ('R' in cellBorders) or ('B' in cellBorders) or ('M' in cellBorders):
print('Cell has border *OR* is a merged cell and borders cannot be checked')
def getCellBorders(ws, cellRef):
tmp = ws[cellRef].border
brdrs = ''
if tmp.top.style is not None: brdrs += 'T'
if tmp.left.style is not None: brdrs += 'L'
if tmp.right.style is not None: brdrs += 'R'
if tmp.bottom.style is not None: brdrs += 'B'
if (brdrs == '') and ('condTableTopLeftCell' in refs):
if fnIsCellWithinMergedRange(ws, cellRef): brdrs = 'M'
return brdrs
def fnIsCellWithinMergedRange(ws, cellRef):
ans = False
col = fnAlphaToNum(re.sub('[^A-Z]', '', cellRef))
row = re.sub('[^0-9]', '', cellRef)
for cell in ws.merged_cells.ranges:
if (int(cell.min_row) <= int(row) <= int(cell.max_row)) and (int(cell.min_col) <= int(col) <= int(cell.max_col)):
ans = True
return ans
def fnAlphaToNum(ltr):
ab = ["MT", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
return ab.index(ltr)
References:
OpenPyXL - How to query cell borders?
How to detect merged cells in excel with openpyxl
https://bitbucket.org/openpyxl/openpyxl/issues/911/borders-on-merged-cells-are-not-preserved

Related

Get Column Index based on Value rather than Column Label

Say I have the following Dataframe.
df = pd.DataFrame([["a", "b", "c"], ["d", "e", "f"],["g", "h", "i"]])
How do I get the column index of "c" in row 0?
I know there are ways to get the column index if there are column labels, but I can't find ways to return the column index just based on the cell value, if searching a particular row.
Like this:
df[df[df.eq("c").any(1)].T.eq("c").any(1)].index[0]
2
Here's one way:
You can create a extra dataframe that check each cell value in your original dataframe to locate the string inside each cell. Here you would like to find c which can be mapped as follow:
check_df = df.applymap(lambda in_each_cell_value: str(in_each_cell_value).find("c") >= 0)
The check_df returns the boolean values and locates the string in the cell.
From the above 'check_df' you can extract and keep the column where the cell was found:
[column for column, count in check_df.sum().to_dict().items()
if count > 0]
Complete code:
df = pd.DataFrame([["a", "b", "c"], ["d", "e", "f"],["g", "h", "i"]])
check_df = df.applymap(lambda in_each_cell_value: str(in_each_cell_value).find("c") >= 0)
ind = [column for column, count in check_df.sum().to_dict().items()
if count > 0]
Outputs:
ind[0]
2

R function within SQL stored procedure issue

I'm attempting to set up a simple R function using SQL stored procedure but I can't get it to work without errors.
Here is my script
CREATE PROCEDURE sp_aggregate (#paramGroup nvarchar(40))
AS
EXECUTE sp_execute_external_script
#language =N'R',
#script=N'
library(dplyr)
data <- data.frame(x = c(1,2,3,4,5,6,7,8,9,10), Country = c("A", "A","A","A","A",
"B", "B", "B", "B", "B"), Class = c("C", "C", "C", "C", "C", "D", "D", "D", "D", "D"))
agg_function <- function(df, column) {
enq_column <- enquo(column)
output <- df %>% group_by(!!enq_column) %>% summarize(total = sum(x))
return(output)
}
OutputDataSet <- as.data.frame(agg_function(df = data, column = paramgroup_var))
'
, #input_data_1 = N''
-- , #input_data_1_name = N'SQL_input'
, #output_data_1_name = N'OutputDataSet'
, #params = N'#paramgroup_var nvarchar(40)'
, #paramgroup_var = #paramGroup;
GO
Execute sp_aggregate #paramGroup = Country
This is the error I'm running into:
Error in grouped_df_impl(data, unname(vars), drop) :
Column `paramgroup_var` is unknown
Calls: source ... group_by.data.frame -> grouped_df -> grouped_df_impl
Error in execution. Check the output for more information.
Error in eval(ei, envir) :
Error in execution. Check the output for more information.
Calls: runScriptFile -> source -> withVisible -> eval -> eval -> .Call
Execution halted
The error is from missing a ) at the end of the data.frame()
CREATE PROCEDURE sp_aggregate (#paramGroup nvarchar(40))
AS
EXECUTE sp_execute_external_script
#language =N'R',
#script=N'
library(dplyr)
data <- data.frame(x = c(1,2,3,4,5,6,7,8,9,10),
Country = c("A", "A","A","A","A", "B", "B", "B", "B", "B"),
Class = c("C", "C", "C", "C", "C", "D", "D", "D", "D", "D"))
agg_function <- function(df, column) {
enq_column <- enquo(column)
output <- df %>% group_by(!!enq_column) %>% summarize(total = sum(x))
return(output)
}
OutputDataSet <- as.data.frame(agg_function(df = data, column = paramgroup_var))
'
, #input_data_1 = N''
-- , #input_data_1_name = N'SQL_input'
, #output_data_1_name = N'OutputDataSet'
, #params = N'#paramgroup_var nvarchar(40)'
, #paramgroup_var = #paramGroup;
GO

Convert bit string array to byte array

I have the following binary string (actually a bit array)
"1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0"
which I want to convert to a byte array.
I need this for an embedded report code functions which only accepts a byte array. I've converted this function from powershell.
I found this but it's C#
string source = "1,1,1,0,0";
byte[] result = source
.Split(',')
.Select(item => byte.Parse(item))
.ToArray();
This does not work in report builder ('Select' is not a member of 'System.Array'.)
Dim source As String = "1,1,1,0,0"
Dim result As Byte() = source.Split(","c).[Select](Function(item) Byte.Parse(item)).ToArray()
If I add System.Linq as suggested I'm still getting an error:
'Select' is not a member of 'Linq'.
Dim source As String() = "1,1,1,0,0".Split(","c)
Dim result As Byte() = System.Linq.Select(Function(source) Byte.Parse(source)).ToArray()
After looking at the function more closely I realized that the input can be any array so I modified the type of the array to string and updated my input accordingly. Tank you guys for trying to help.
Function
Function GetSQLProductKey(ByVal astrBinaryKey As String(), ByVal intVersion As Integer) As String
Dim achrKeyChars As Char() = {"B", "C", "D", "F", "G", "H", "J", "K", "M", "P", "Q", "R", "T", "V", "W", "X", "Y", "2", "3", "4", "6", "7", "8", "9"}
Dim strSQLProductKey As String
Dim iastrBinaryKey As Long
Dim iachrKeyChars As Long
Dim iastrBinaryKeyOuterLoop As Long
Dim iastrBinaryKeyInnerLoop As Long
Try
If (intVersion >= 11) Then
iastrBinaryKey = 0
Else
iastrBinaryKey = 52
End If
For iastrBinaryKeyOuterLoop = 24 To 0 Step -1
iachrKeyChars = 0
For iastrBinaryKeyInnerLoop = 14 To 0 Step -1
iachrKeyChars = iachrKeyChars * 256 Xor astrBinaryKey(iastrBinaryKeyInnerLoop + iastrBinaryKey)
astrBinaryKey(iastrBinaryKeyInnerLoop + iastrBinaryKey) = Math.Truncate(iachrKeyChars / 24)
iachrKeyChars = iachrKeyChars Mod 24
Next iastrBinaryKeyInnerLoop
strSQLProductKey = achrKeyChars(iachrKeyChars) + strSQLProductKey
If (iastrBinaryKeyOuterLoop Mod 5) = 0 And iastrBinaryKeyOuterLoop <> 0 Then
strSQLProductKey = "-" + strSQLProductKey
End If
Next iastrBinaryKeyOuterLoop
Catch
strSQLProductKey = "Cannot decode product key."
End Try
GetSQLProductKey = strSQLProductKey
End Function
Function Call SSRS
Code.GetSQLProductKey(Split(Replace(Fields!ProductKey.Value, " ",""), ","), Left(Fields!Version.Value, 2))

Referencing Matrix (VB)

I have a matrix (5x5) with values in them for example:
Matrix (1,1) Value: 'a'
Matrix (1, 2) Value: 'b'
Matrix (2, 1) Value: 'c'
how would I be able to find the letter 'a' in that matrix and have it output the coordinates?
ie
user inputs 'b'
[searches for 'b' in table]
output (1,2)
thanks in advance
It's as simple as:
For i As Integer = 0 To LengthOfMatrix - 1
For y As Integer = 0 To HeightOfMatrix - 1
If Matrix(i, y) = "a" Then Console.Write(i & " " & y & vbCrLf)
Next
Next
Asuming that you declared Matrix as:
Dim Matrix As Char(,) = {{"a", "b", "c", "d", "e"}, {"a", "b", "c", "d", "e"}, {"a", "b", "c", "d", "e"}, {"a", "b", "c", "d", "e"}, {"a", "b", "c", "d", "e"}}
And LengthOfMatrix And HeightOfMatrix should be the dimentions of your matrix. They could be switched to something more dynamic like:
For i As Integer = 0 To Matrix.GetLength(0) - 1 'Get's the length of the first dimension
For y As Integer = 0 To Matrix.GetLength(1) - 1 'Get's the length of the second dimension
If Matrix(i, y) = "a" Then Console.Write(i & " " & y & vbCrLf)
Next
Next
In a short description, all that this loop does is it goes through all of the elements of the matrix and outputs the coordinates of every element that matches a certain criteria (In this case - equals to 'a').
Note: In most programming languages array's indexes begin from 0, so the first element in your matrix will be at coords (0,0).

An SQL statement into SSRS

I tried to incorporate the following into SSRS but failed.
If XXX = “A” then display “AT”
Else if XXX = “B” then display “BEE”
Else if XXX = “C” then display “CAR”
Else display “Other”
I tried
=Switch(
Fields!XXX.Value = "A", "AT",
Fields!XXX.Value = "B", "BEE",
Fields!XXX.Value = "C", "CAR", "Other")
You almost had it. For every output in the Switch function must be paired with a condition. Just make your last condition evaluate to True.
=Switch(
Fields!XXX.Value = "A", "AT",
Fields!XXX.Value = "B", "BEE",
Fields!XXX.Value = "C", "CAR",
True, "Other"
)
You want something like this:
=iif(Fields!XXX.Value = "A", "AT", iif(Fields!XXX.Value = "B", "BEE", iif(Fields!XXX.Value = "C", "CAR", "Other")))
[check the parens in the expression builder]