Algorithm / Code to find dependency and build row column wise hierarchy model using VBA - excel

Suppose I have two columns ColA = Calling programs and ColB = Called programs, now I want to build a hierarchy between calling and called program and print them with the calling dependency lvl column as below.
Note:
Calling program for which called program is SPACES, is the initial program for a new branch.
Output representation can differ, but it has to be in row and column only.
Input columns:
COLA COLB
AAA
AAA BBB
AAA CCC
BBB
BBB CCC
CCC DDD
CCC GGG
CCC HHH
DDD
DDD III
DDD MMM
EEE
EEE BBB
EEE FFF
EEE JJJ
EEE KKK
FFF
FFF LLL
FFF MMM
FFF NNN
MMM OOO
Output:
COLA(Initial) LVL COLB(Calling) COLC(Called)
AAA 1
AAA 2 BBB
AAA 3 CCC
AAA 4 DDD
AAA 5 III
AAA 5 MMM
AAA 6 OOO
AAA 4 GGG
AAA 4 HHH
AAA 2 CCC
AAA 3 DDD
AAA 4 III
AAA 4 MMM
AAA 5 OOO
AAA 3 GGG
AAA 3 HHH
BBB 1
BBB 2 CCC
BBB 3 DDD
BBB 4 III
BBB 4 MMM
BBB 5 OOO
BBB 3 GGG
BBB 3 HHH
DDD 1
DDD 2 III
DDD 2 MMM
DDD 3 OOO
EEE 1
EEE 2 FFF
EEE 3 LLL
EEE 3 MMM
EEE 4 OOO
EEE 3 NNN
EEE 2 JJJ
EEE 2 KKK
FFF 1
FFF 2 LLL
FFF 2 MMM
FFF 3 OOO
FFF 2 NNN
I tried, but I am stuck at LVL 4 and the recursive loop. Please suggest
for i = 1 to i <= last row
lvl_no = 0
if CCi == SPACES
OBJECT_NAME = CAi
lvl_no = 1
copy row i to new excel
for j = 1 to j <= last row
if CAj = OBJECT_NAME && CCj != SPACES
lvl_no = 1 + 1
copy row j to new excel
dep_obj = CCj
ROW = 1 BBB
function_dep(dep_obj,lvl_no,ROW)
j++
ELSE J++
function_dep (object_name, lvl, row)
{
for k=row to k<= last_row
if CAk = object_name && CCk !=spaces
lvl = lvl + 1
dep_obj = CCk
row = 1
print line k, lvl
call function_dep(dep_obj, lvl, row)
else k++
}
As per the below comment suggestion I updated my input with some new rows like (DDD , EEE BBB and MMM OOO), and as per the input the output also got updated with new levels as per dependencies.
Below suggested solution no working for me, as for EEE->BBB dependency it is only showing single row EEE->BBB and missed the whole forward dependencies (EEE->BBB->CCC->DDD and so on) considering it as a duplicate.

Related

TCL threads not running simultaneously?

I am working on a task, which must be solved in TCL. Because this task involves communication with several IO devices in parallel, I thought to solve it with threads. Because I observed problems, I wrote this TCL script, to test the threading behavior:
package require Thread
set t1 [thread::create {
for {set i 0} {$i < 10} {incr i} {
puts "AAA $i"
after 50
}
}]
puts "Created thread t1"
set t2 [thread::create {
for {set i 0} {$i < 10} {incr i} {
puts "BBB $i"
after 50
}
}]
puts "Created thread t2"
# ---------------------------
after 1000
proc threadprocSync {msg n} {
for {set i 0} {$i < $n} {incr i} {
puts "$msg $i"
after 50
}
}
set t3 [thread::create [threadprocSync "CCC" 10]]
puts "Created thread t3"
set t4 [thread::create [threadprocSync "DDD" 10]]
puts "Created thread t4"
# ---------------------------
after 1000
proc outproc {msg i} {
puts "$msg $i"
}
proc threadprocAsync {t msg n} {
for {set i 0} {$i < $n} {incr i} {
thread::send -async $t [outproc $msg $i]
after 50
}
}
set tWorker [thread::create -preserved]
puts "Created thread tWorker"
# ---------------------------
set t5 [thread::create [threadprocAsync $tWorker "EEE" 10]]
puts "Created thread t5"
set t6 [thread::create [threadprocAsync $tWorker "FFF" 10]]
puts "Created thread t6"
# ---------------------------
after 1000
thread::release $tWorker
The code contains delays of 50 ms to make the execution slower, so that the threads needs significantly more time, than the initialization of the environment. But I observe here, that only the first pair of threads, which print AAA and BBB runs simultaneously. I expected the same behavior also for the threads with CCC and DDD and for the threads with EEE and FFF. What am I doing wrong?
The above script produces the following output:
C:\Projects\tcltest>tclsh threads.tcl
Created thread t1
AAA 0
Created thread t2
BBB 0
AAA 1
BBB 1
AAA 2
BBB 2
AAA 3
BBB 3
BBB 4
AAA 4
AAA 5
BBB 5
AAA 6
BBB 6
BBB 7
AAA 7
AAA 8
BBB 8
AAA 9
BBB 9
CCC 0
CCC 1
CCC 2
CCC 3
CCC 4
CCC 5
CCC 6
CCC 7
CCC 8
CCC 9
Created thread t3
DDD 0
DDD 1
DDD 2
DDD 3
DDD 4
DDD 5
DDD 6
DDD 7
DDD 8
DDD 9
Created thread t4
Created thread tWorker
EEE 0
EEE 1
EEE 2
EEE 3
EEE 4
EEE 5
EEE 6
EEE 7
EEE 8
EEE 9
Created thread t5
FFF 0
FFF 1
FFF 2
FFF 3
FFF 4
FFF 5
FFF 6
FFF 7
FFF 8
FFF 9
Created thread t6
C:\Projects\tcltest>

Excel formula to find specific data based on max row result

Good day beautiful people of Scotl... Stackoverflow.
I have faced issue in Excel which I have no idea how to solve. I tried many formulas but I believe that the problem is in my mind, since I have troubles to imagine the logical way it should follow.
I have attached a screenshot to clarify my problem:
Excel screenshot
Description of a screenshot
Column B - data name,
Rows C3:H3 - product name,
Table C4:H15 - some data (description, dates, etc.).
Column I is my extra and it is not mandatory to be there.
Desired result
I want to get data from table above to the table below but if there is one or more "DataX", I want Excel to pick the "DataX" where the biggest amount of rows are filled up (I have marked them blue for each DataX).
For example, for:
Data 1 - row 4,
Data 2 - row 7,
Data 3 - (obviously) row 9,
Data 4 - rows 11,
Data 5 - row 13.
If one or more records will match (all rows are empty / filled up), I don't care which row will be presented as a result.
What I have tried
I have added calculation (column I) which shows how many rows were updated and I was trying to find combination of v,hlookup + max but it wasn't working correctly.
I also created VBA code for it, which was working... almost good but then I received information that macros are no-go zone for this project.
Logic
I strongly believe that the logic should be as following:
Find matching DataX,
Find max value in row I (or include it in formula),
Find corresponding rows / columns for this record.
A
B
C
D
E
F
G
H
I
2
CAT 1
CAT 2
CAT 3
CAT 4
CAT 5
CAT 6
Count not blank
3
1
2
3
4
5
6
4
Data 1
AAA
BBB
CCC
EEE
FFF
=$H$3-COUNTBLANK(C4:H4)
5
Data 1
BBB
CCC
DDD
=$H$3-COUNTBLANK(C5:H5)
6
Data 1
AAA
BBB
EEE
FFF
=$H$3-COUNTBLANK(C6:H6)
7
Data 2
AAA
BBB
CCC
DDD
EEE
FFF
=$H$3-COUNTBLANK(C7:H7)
8
Data 2
AAA
BBB
CCC
DDD
FFF
=$H$3-COUNTBLANK(C8:H8)
9
Data 3
AAA
BBB
CCC
EEE
FFF
=$H$3-COUNTBLANK(C9:H9)
10
Data 4
CCC
DDD
EEE
FFF
=$H$3-COUNTBLANK(C10:H10)
11
Data 4
AAA
BBB
CCC
DDD
FFF
=$H$3-COUNTBLANK(C11:H11)
12
Data 4
AAA
BBB
CCC
EEE
FFF
=$H$3-COUNTBLANK(C12:H12)
13
Data 5
AAA
BBB
CCC
DDD
EEE
FFF
=$H$3-COUNTBLANK(C13:H13)
14
Data 5
BBB
CCC
DDD
EEE
FFF
=$H$3-COUNTBLANK(C14:H14)
15
Data 5
AAA
BBB
DDD
EEE
FFF
=$H$3-COUNTBLANK(C15:H15)
Hello dear son of Scotl.. overflow!
Please add to column J (range J4:J15) this additional formula
=CONCATENATE(B4,I4)
and then paste this to C19:
=INDEX(C$4:C$15,MATCH(CONCATENATE($B19,MAX(IF($B$4:$B$15=$B19,$I$4:$I$15,0))), $J$4:$J$15,0))
paste it as an array formula, i.e. press Ctrl+Shift+Enter simultaneously. Then populate it to the rest of the desired range.
The numbers in my example table do not mean anything, it's the number in I that matters.
Regards!!

how can I calculate how many each product a person has bought

how can I calculate how many each product a person has bought if I have a dictionary in which there is a surname, type of product and how much he bought it
Here is my code that makes a dictionary:
with open("Input_1.txt", "r") as file:
dict_2 = {}
for line in file:
Surname = line.split() [0]
Item = line.split()[1]
Amount=line.split()[2]
dict_2[Surname] = {Item: Amount}
print(dict_2)
for example what it have to print:
{"Ivanov"{"aaa" 23} , "Petrov"{"aaa" 58} and so on
This is data from my txt file:
Ivanov aaa 1
Petrov aaa 2
Sidorov aaa 3
Ivanov aaa 6
Petrov aaa 7
Sidorov aaa 8
Ivanov bbb 3
Petrov bbb 7
Sidorov aaa 345
Ivanov ccc 45
Petrov ddd 34
Ziborov eee 234
Ivanov aaa 45
Ivanov paper 10
Petrov pens 5
Ivanov marker 3
Ivanov paper 7
Petrov envelope 20
Ivanov envelope 5
If you want a simple python solution you may change your code to:
with open('Input_1.txt', 'r') as file:
dict_2 = {}
for line in file:
surname, item, amount = line.split()
amount = int(amount)
if surname not in dict_2:
dict_2[surname] = {}
if item not in dict_2[surname]:
dict_2[surname][item] = amount
else:
dict_2[surname][item] += amount
This will give you the following dictionary:
Ivanov
aaa : 52
bbb : 3
ccc : 45
paper : 17
marker : 3
envelope : 5
Petrov
aaa : 9
bbb : 7
ddd : 34
pens : 5
envelope : 20
Sidorov
aaa : 356
Ziborov
eee : 234
But it may be a good chance to give the pandas package a try. It's pretty useful when working with your kind of data. See the same code as above but using pandas
import pandas as pd
my_data = pd.read_csv('Input_1.txt', names=['Surname', 'Item', 'Amount'], sep=' ')
result = my_data.groupby(['Surname', 'Item']).sum()
print(result)
This gives you the following DataFrame:
Amount
Surname Item
Ivanov aaa 52
bbb 3
ccc 45
envelope 5
marker 3
paper 17
Petrov aaa 9
bbb 7
ddd 34
envelope 20
pens 5
Sidorov aaa 356
Ziborov eee 234

vba macro: Alternate value display on the loop and limiting selection on curren region

I created a list of numbers on 1st sheet then on 2nd sheet I created some details where one of the cell will get the value of the cell on the 1st sheet(thru loop)
My script is working but got some issues:
- It gets the value of the 1st row but also gets the value on displayed on the 2nd row.
- It exceeded the number of Loops based on the number of rows on my 1st sheet.
- It's overrides the formula concatenate on my cell.
- It doubles the spaces after pasting
Codes:
Public Sub Number()
Dim i, Lastrow As Integer
Dim valueCT As String
Worksheets("Sheet2").Select
Lastrow = ActiveSheet.Range("A2").End(xlDown).Row
For i = 1 To Lastrow
Worksheets("Sheet3").Select
Range("C2").Select
Range("C" & i + 1).Value = Worksheets("Sheet2").Range("A" & i + 1).Value
Selection.CurrentRegion.Select
Selection.Copy
Range("C" & i + 2).Value = Range("C" & i + 1).Value
Range("C500").Select
Selection.End(xlUp).Select
ActiveCell.Offset(3, 0).Select
ActiveSheet.Paste
Next
End Sub
Number List
Column A - 1st Sheet
Number
2845
2846
2847
2848
2849
2850
2851
Second Sheet column C:F , 2 rows
With formulas on 1st row cell "=" and concatenate on 2nd row cell
2845 AAA BBBB BBBCCC
2845BBBCCC AAA BBBB BBBCCC
My expected result is to display all numbers that included on my list
then copy only the first selection on the current region of the 2nd sheet
expected result:
2845 AAA BBB CCC
2845AAA AAA BBB CCC
2845BBB AAA BBB CCC
2845CCC AAA BBB CCC
2846 AAA BBB CCC
2846AAA AAA BBB CCC
2846BBB AAA BBB CCC
2846CCC AAA BBB CCC
2847 AAA BBB CCC
2847AAA AAA BBB CCC
2847BBB AAA BBB CCC
2847CCC AAA BBB CCC
Current/ Actual result:
2845 AAA BBB CCC
2846 AAA BBB CCC
2847 AAA BBB CCC
AAA BBB CCC
2845 AAA BBB CCC
AAA BBB CCC
2845 AAA BBB CCC
2846 AAA BBB CCC
2846 AAA BBB CCC
2845 AAA BBB CCC
2846 AAA BBB CCC
2847 AAA BBB CCC
2845 AAA BBB CCC
2846 AAA BBB CCC
2847 AAA BBB CCC

Find match and if true replace

So what I would like to be able to do is take a list and if there is a match below a cell I want to use this formula =--REPLACE(A1,1,2,99).
I have this which will mark them true. However I want to use the fromula from above.
=IF(COUNTIF(A1,"="&A2),"True","")
Example
1111111 AAA = 1111111
2222222 BBB = 2222222
3333333 CCC = 9933333
4444444 CCC = 4444444
5555555 DDD = 5555555
6666666 EEE = 9966666
7777777 EEE = 7777777
8888888 FFF = 8888888
No need for the COUNTIF() Just use this:
=IF(B1=B2,--REPLACE(A1,1,2,99),A1)

Resources