Mathematical transpose in excel - excel

Good day everybody!
I'm currently trying to figure something out in excel before implementing in it VBScript. I have to mathematically transpose a few cells (10*10 or 5r*10c) in a matrice:
-------------------------------
| .. | .. | .. | .. | .. | .. |
| 21 | 22 | 23 | 24 | 25 | .. |
| 11 | 12 | 13 | 14 | 15 | .. |
| 1 | 2 | 3 | 4 | 5 | .. |
-------------------------------
Must become
-------------------------------
| .. | .. | .. | .. | .. | .. |
| 3 | 13 | 23 | 33 | 43 | .. |
| 2 | 12 | 22 | 32 | 42 | .. |
| 1 | 11 | 21 | 31 | 41 | .. |
-------------------------------
Now I'm not a mathematician (I'm more ore less a programmer at the moment), but I came up with: F(y)=((MOD(x,10)-1)*10)+(1+((x-MOD(x,10))/10)) (x is the value in the pre-block a the top, y is the value in the pre-block below.) Now this works fine up to a certain point (e.g. 10).
In VBScript, I wrote the below at first:
Function GetPosInSrcRack(Pos)
Dim PlateDef(9), x, y, i, tmp
' Plate Definition
ReDim tmp(UBound(PlateDef))
For x = 0 To UBound(PlateDef)
PlateDef(x) = tmp
Next
i = 1
For x = 0 To UBound(PlateDef)
For y = 0 To UBound(PlateDef(x))
PlateDef(x)(y) = i
i = (i + 1)
Next
Next
'Dim msg ' Check definition
'For x = 0 To (UBound(PlateDef))
' msg = Join(PlateDef(x), ", ") & vbCrLf & msg
'Next
' Get the Position
y = (pos Mod 10)
x = ((pos - y) / 10)
GetPosInSrcRack = PlateDef(y)(x)
End Function
Which, of course, works but is crappy.
Using the above formula I would write:
Function GetPosInSrcRack(Pos)
Pos = (((Pos MOD 10)-1)*10)+(1+((Pos - (Pos MOD 10))/10))
End Function
But like I said, this still is incorrect (10 gives -8)
Can somebody help me?

Just use Paste Special > Transpose option.

y=(MOD(x-1,10))*10+INT((x-1)/10)+1
(By the way, what you are doing is not matrix transposition, but this does do what you do, only better.)

Related

SUMPRODUCT with LEN

Good day! I have a table in Excel. The first line contains the norms. The rest of the lines contain days.
I need to calculate the costs by multiplying the norms by the number of days:
5*LEN(345) + 2*LEN(2) + 9*LEN(67) + 4*LEN(23) = 5*3 + 2*1 + 9*2 + 4*2 = 43
5*LEN(12) + 2*LEN(23) + 9*LEN(4) + 4*LEN(567) = ...
5*LEN(4) + 2*LEN(45) + 9*LEN(34) + 4*LEN(12) = ...
|--------|--------|--------|--------|--------|--------|--------|
| | B | C | D | ... | H | |
|--------|--------|--------|--------|--------|--------|--------|
| 4 | norm | 5 | 2 | 9 | 4 | |
|--------|--------|--------|--------|--------|--------|--------|
| 5 | days | 345 | 2 | 67 | 23 | sum? |
|--------|--------|--------|--------|--------|--------|--------|
| 6 | days | 12 | 23 | 4 | 567 | sum? |
|--------|--------|--------|--------|--------|--------|--------|
| 7 | days | 4 | 45 | 34 | 12 | sum? |
|--------|--------|--------|--------|--------|--------|--------|
How do I write this as a formula? I tried
=SUMPRODUCT(C$4:H$4,C5:LEN(H5))
or
{=SUMPRODUCT(C$4:H$4,C5:LEN(H5))},
it doesn't work ...
You are nearly there
try this
=SUMPRODUCT(C$4:H$4,LEN(C5:H5))

Python previous month with 2 digit

I want 04 as output in premonth . Can some one help on this? tried diff format and no luck.
enter code here
premonth = str(int(time.strftime('%m'))-1)
tried using
python date of the previous month
but due to strftime restriction I am not able to proceed.
Not the best way but this should work:
a = str(int(time.strftime('%m'))-1)
a = '0'+a if len(a)==1 else a
The following f-string will give you what you need, it also handles January correctly by using arithmetic manipulation to ensure 1 becomes 12:
f'{(int(time.strftime("%m")) + 10) % 12 + 1:02}'
Breaking that down, an f-string is a modern way to build strings from arbitrary expressions, in a way that keeps formatting and data together (unlike the old "string".format(item, item) and even older "string" % (item, item)).
Inside that f-string is a rather complex looking expression which is formatted with :02, meaning two places, zero-padded on left.
The expression is what correctly decrements your month with proper wrapping, as you can see from the following table:
+-------+-----+-----+----++-------+-----+-----+----+
| Value | +10 | %12 | +1 || Value | +10 | %12 | +1 |
+-------+-----+-----+----++-------+-----+-----+----+
| 1 | 11 | 11 | 12 || 7 | 17 | 5 | 6 |
| 2 | 12 | 0 | 1 || 8 | 18 | 6 | 7 |
| 3 | 13 | 1 | 2 || 9 | 19 | 7 | 8 |
| 4 | 14 | 2 | 3 || 10 | 20 | 8 | 9 |
| 5 | 15 | 3 | 4 || 11 | 21 | 9 | 10 |
| 6 | 16 | 4 | 5 || 12 | 22 | 10 | 11 |
+-------+-----+-----+----++-------+-----+-----+----+
and the following statement:
print(", ".join([f'{mm}->{(mm + 10) % 12 + 1:02}' for mm in range(1, 13)]))
which outputs:
1->12, 2->01, 3->02, 4->03, 5->04, 6->05, 7->06, 8->07, 9->08, 10->09, 11->10, 12->11

How to interpolate zero cells in a large excel sheet?

I have a long excel file which contains numbers collected from a website. Less than 1% of the cells contain zero due to an error from the source. Therefore, I want to find update those cells and interpolate them with the nearest values. The length of the zero cells is some time single, hence I can simply take the average of the nearest non-zero values. However, a few places it is longer than one, hence I need to use linear interpolation.
Sample extracted data
+---+------+------+------+------+------+------+------+------+---+---+---+---+---+---+---+---+------+------+------+------+------+------+------+------+------+
| | 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 |
+---+------+------+------+------+------+------+------+------+---+---+---+---+---+---+---+---+------+------+------+------+------+------+------+------+------+
| 1 | 4058 | 4048 | 4049 | 4082 | 4090 | 4115 | 4118 | 4109 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 3990 | 4058 | 4064 | 4053 | 4057 | 4093 | 4123 | 4137 | 4133 |
+---+------+------+------+------+------+------+------+------+---+---+---+---+---+---+---+---+------+------+------+------+------+------+------+------+------+
Here's a very general script that might do something like that. It is only tested on positive values and ten rows, so you will definitely need to adapt it to many corner cases - but it should point you in the right direction:
Sub Interpolate()
Dim valueToTop As Integer
For Row = 1 To 10
valueToTop = -1
valueToBottom = -1
If Cells(Row, 1).Value = 0 Then
RowToTop = Row - 1
Do While RowToTop > 0
If Cells(RowToTop, 1).Value > 0 Then
valueToTop = Cells(RowToTop, 1)
Exit Do
End If
RowToTop = RowToTop - 1
Loop
Debug.Print valueToTop
Debug.Print RowToTop
RowToBottom = Row + 1
Do While RowToBottom > 0
If Cells(RowToBottom, 1).Value > 0 Then
valueToBottom = Cells(RowToBottom, 1)
Exit Do
End If
RowToBottom = RowToBottom + 1
Loop
Debug.Print valueToBottom
Debug.Print RowToBottom
Cells(Row, 2).Value = valueToTop + (Row - RowToTop) * (valueToBottom - valueToTop) / (RowToBottom - RowToTop)
End If
Next Row
End Sub

Calculating median using two columns

I have the following columns
12 A
11 M
12 B
12 C
11 A
9 M
13 N
11 M
12 C
11 B
15 M
I want to calculate median based on only Ms. I have done by selecting ranges.
I want to use columns rather than ranges. Is there any solution? Thanks for your help
If you have 2010 or later use this formula:
=AGGREGATE(17,6,(A:A/(B:B="M")),2)
If you have 2007 or earlier, try this array formula:
=MEDIAN(IF(B:B="M",A:A))
This is an array formula and must be confirmed with Ctrl-Shift-Enter.
Though the use of full column references will slow the calculation times because it will iterate through all the rows, all 1.04 million. It is good practice to limit the references to the max data range to help offset this drain. Change the C:C to something like $C$1:$C$10000 then it will loop only 10,000 times.
Well as a VBA user I love to use VBA, other can use your skill using formulas, and is completly right if you are good on formulas. Here is my answer and I hope help you.
Imagine you have this:
+----+------------+--------------------+---------------+
| 1 | Values (A) | Criteria Range (B) | Criteria ( C) |
+----+------------+--------------------+---------------+
| 2 | 14 | B | A |
| 3 | 1 | M | |
| 4 | 15 | A | |
| 5 | 15 | E | |
| 6 | 10 | A | |
| 7 | 3 | M | |
| 8 | 11 | A | |
| 9 | 8 | M | |
| 10 | 14 | A | |
| 11 | 5 | M | |
| 12 | 9 | M | |
| 13 | 10 | M | |
| 14 | 11 | N | |
| 15 | 9 | A | |
| 16 | 2 | M | |
| 17 | 15 | M | |
| 18 | 11 | A | |
| 19 | 12 | S | |
| 20 | 9 | M | |
| 21 | 11 | A | |
| 22 | 15 | V | |
+----+------------+--------------------+---------------+
And inside the cell E2 you have this =MedianIf($A$2:$A$22,$B$2:$B$22,C2) and the result must be 11
Because in a regular module of VBA you put this function.
Function MEDIANIF(RangeIf As Range, Criteria_Range1 As Range, Criteria1 As String) As Double
Dim i
Dim Counter
Dim tmp()
Dim subCouter
subCouter = 0
For Each i In Criteria_Range1
Counter = Counter + 1
If i.Value = Criteria1 Then
subCouter = subCouter + 1
ReDim Preserve tmp(1 To subCouter)
tmp(subCouter) = RangeIf(Counter)
End If
Next i
Dim a
MEDIANIF = Application.WorksheetFunction.Median(tmp())
End Function
And the function works like this:
RangeIF = is the range with the values that you want to get the MEDIAN
Criteria_Range1 = Is the range where you have all the criteria, is the same size as RangeIF
Criteria1 = Is the criteria you use to filter the data.
How about this low-tech solution:
In Column C, formulate: =IF(B2="M",A2,"") (in rows 2-12, based on your data, and assuming row 1 contains headers)
In cell D2 (or anywhere else), formulate: =MEDIAN(C:C)

How to count the numeric values from cell

I have values in cell like.
1,2,4,45,64,Jan. Ans: 5
I want to count only number from the cell.
Is it possible?
You could also use the split function in a UDF:
Function CountNumbers(R As Range) As Integer
Dim values, value As Variant
Dim result As Integer
values = Split(R.Text, ",")
result = 0
For Each value In values
If IsNumeric(value) Then
result = result + 1
End If
Next value
CountNumbers = result
End Function
From here, you could call it within another Excel cell as:
=CountNumbers(A1)
Here is my answer:
Sub countingNumbers()
Dim c As Range
Dim L As Long
Dim s As String
Dim tmp
Dim i
Dim y
Set c = Range("A1") 'Imagine in A1 is this: "RDFY2372784GDTD2GV3G3G3V3"
L = Len(c.Value) 'to store the len of the string
s = c.Value 'to store the string
y = 0 'the index of the numbers
For i = 1 To L
tmp = Left(Right(s, i), 1) 'to take just one letter at the time
If Asc(tmp) < 57 And Asc(tmp) > 48 Then
'if is a number ASC() returns the ASCII code of that number
'and increase y one by one || that is number by number
y = y + 1
End If
Next i
Range("B2").Value = y 'store the counting in B2
End Sub
Part of the ASCII Table:
+------------+-----------+
| ASCII Code | Character |
+------------+-----------+
| 48 | 0 |
| 49 | 1 |
| 50 | 2 |
| 51 | 3 |
| 52 | 4 |
| 53 | 5 |
| 54 | 6 |
| 55 | 7 |
| 56 | 8 |
| 57 | 9 |
| 64 | # |
| 65 | A |
| 66 | B |
| 67 | C |
| 68 | D |
| 69 | E |
| 70 | F |
| 71 | G |
| 72 | H |
| 73 | I |
| 74 | J |
+------------+-----------+
Here you can check the ASCII table

Resources