MS Project VBA - linking non-consecutive tasks - vba

I have created tasks in MS project( by using VBA) from an excel sheet.
Each row on the excel sheet, has multiple task through different phases.
For e.g.
For Item 1 on the excel sheet
Phase 1
Task Item 1 is created ( meant as a summary task) , With 4 identifying field( 1 of them is phase 1)
Subtask Item1
Subtask Item2
Phase 2
Task Item 1 is created ( summary task ), with 4 identifying fields ( 1 of them is phase 2)
Subtask Item 1
Subtask Item 2
Subtask Item 3
I have no issues with linking and outlining the subtasks as long as they are consecutive.
I can't figure out how to link let's say
Phase1.Item1.subtask2 to Phase 2.Item 1.subtask3
What are the possible ways to do this ? ( I have thought about, IF Task.Text6= Tasks.Text6 then link, but i need a way to go through the entire task list and assign 2 variables( I think...) but the for each loop stops after the condition is true,....
Absolute Newbie here.
Appreciate any ideas.

Related

how to load set of records in one table and others set of records to different table in ssis

I have a scenario based question here.
Say I have a table which was million of records with few columns.I want to load the data to two different destination in ssis based on number of rows first 3 rows should go to one table and second set of three row should go to other table and this should repeat until all the records loaded to the two destinations.
Table1:
ID
1
2
3
4
5
6
7
8
9
10
11
12
So first Target table should have records
1
2
3
7
8
9
and Second table should have
4
5
6
10
11
12
Please let me now the approach
Solution (1): Using SQL (DENSE_RANK(), MODULO) + Conditional Split
You can use a similar SQL Command as OLEDB Source, it will generate a Column that split the data based on the row number.
SELECT ID, DENSE_RANK() OVER(PARTITION BY ID % 3 ORDER BY ID) % 2 as DestinationTable
FROM Table1 ORDER BY ID
After that you can use a conditional split component to split the flow into rwo destination.
Note: When handling a huge amount of data, you have to make sure that you have created the corresponding indexes)
Solution (2): Using Script Component + Conditional Split
First you have the OLEDB connection manager you need (Source and Destination Connections)
Add a Data Flow Task
In the Data flow task, add an OLEDB Source which read from the Source Table
Add A Script Component where you need to implement the logic you described and you have to add an output column that contains the Destination Table ID.
Script Code (VB.NET)
Public Class ScriptMain
Inherits UserComponent
Private RowCounter As Integer = 0
Private DestinationTableID As Integer = 1
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
RowCounter += 1
Row.DestinationTable = DestinationTableID
If RowCounter = 3 Then
RowCounter = 0
If DestinationTableID = 1 Then
DestinationTableID = 2
Else
DestinationTableID = 1
End If
End If
End Sub
End Class
Add A conditional Split that split the flow based on the Table ID (If Table ID == 1 than insert data into Destination 1 else Destination 2)
Connect each flow to the corresponding Destination
Remark
If your goal is to distribute the data into two destination without any condition, you can only use only a conditional split transformation to split the data using (modulo) using the following expression (where 2 is the number of destination you need)
Row.ID % 2 == 0
Or you can use the Balanced Data Distributor to achieve that without any manual implementation.
you can use Conditional Split Transformation. For this,
Click the Data Flow tab, and, from the Toolbox, drag the Conditional Split transformation to the design surface.
Connect the Conditional Split transformation to the data flow by dragging the connector from the data source
Double-click the Conditional Split transformation.
In the Conditional Split Transformation Editor, build the expressions to use as conditions by dragging variables, columns, functions, and operators to the Condition column in the grid. Or, you can type the expression in the Condition column.
The Click Ok.
In your case flow conditions can be ID % != 0 and ID % 3 == 0

When using the indirect function it does not move data down with it

I have a back end of data in my workbook, the sheet is called "Task List". This is just a list of tasks listed in this sheet in column A.
Then I have 4 separate sheets that reference these tasks with the =indirect("'Task List'!A"&ROW()-5) function and in these 4 sheets. My problem is that in the 4 sheets, each row has a list of data that goes with it, so when a new task is added in the "task list" sheet (added between cells), the data does not move downward with the task, instead, the data stays put while just the task list moves down...to explain more clearly i have shown this below:
Task List Data Sheet 1 Data Items
task 1 Task 1 Data 1
task 2 Task 2 Data 2
task 3 Task 3 Data 3
task 4 Task 4 Data 4
task 5 Task 5 Data 5
Now when a new task is inserted....
Task List Data Sheet 1 Data Items
task 1 task 1 Data 1
task 2 task 2 Data 2
NEW TASK INSERTED HERE NEW TASK INSERTED HERE Data 3
task 3 task 3 Data 4
task 4 task 4 Data 5
task 5 task 5 BLANK
As you can see, the data stays put above in the example. Is there any way to make data move with the indirect funcction or is there a better way of doing this? - The reason the sheet is build this way is that the tasks in the task list have to go into 5 sheets and it saves time having to copy the task into each sheet when a new one has to be added.
If you are committed to using the INDIRECT method of referencing the cells, consider adding in a method of indexing your data and pulling in your other columns based on the Task name.
For example - assume that in all sheets, column A holds the unique task name.
In column B on your data items tab, if you want to pull in the data associated with the unique task name in column A from one of your other sheets, you can do so as follows [shown for B2]:
=INDEX(Sheet1!B:B,MATCH(A2,Sheet1!$A:$A,0))
If you copy this down and right it will automatically pick up all cells in that order, matched by the unique ID, which uses an INDIRECT reference to always point to a given Grid reference.

Sum data in a column based on another column Report Builder - Sharepoint

I have a project where I have to report stop times of different production lines.
I have to make a report file with Report Builder and my problem for the moment is that I have to sum all the stop times that where entered for the same line.
The stop times are entered on SharePoint (using a form from InfoPath) and stored in a SharePoint List.
My data list is presented like this:
LINES ---- TIME(min)
Line 1 ---- 4
Line 2 ---- 2
Line 1 ---- 3
Line 3 ---- 8
Line 4 ---- 9
Line 2 ---- 2
Line 3 ---- 4
Line 5 ---- 5
Line 5 ---- 8
I want to sum all the stop time for each line (In my report generated with Report Builder). So I'll have "Line1 -> 7", "Line 2 -> 4",...
Do you have any idea how I could do it?
Ask if you need more informations...
Thank you for your help!
This should be fairly easy; set up a table drawing the data in exactly that format, then right click the "Details" row in "Row Groups" at the bottom of Report Builder and click "Group Properties". Press Add, and select your "Lines" field, then press OK. Finally, change the expression populating the "Time" column in your table to =SUM(Fields!.Value).
What this will do is collapse the table to show one line per distinct value it finds in the "Lines" column, then tells it to simply add all the values it collapses together. The effect will be that it sums up the Time column for each distinct value it finds in the Lines column.

Using a 3-column Collection in Excel VBA and searching it

I am building an algorithm in excel vba to search for paths in a network. I am new to programming these types of problems. Please don't suggest alternate software. The problem should be very simple.
Problem Description:
Search a collection of data representing flows on arcs (3 "columns": from, to, flow)
Identify path (start at source, find flow to "to", look up that "to" in the "from" field, find flow to that "to", and so on until another "from" cannot be found) from source to end of each path.
Data looks like this:
fromnode tonode flow
1 2 4
2 3 3
3 4 2
4 5 1
7 6 1
8 7 2
Biggest hurdle:
I am using a Collection to hold this data and setting it with the code below.
Dim y As Collection
Set y = New Collection
y.Add Sheets("FlowDecomp_Solve").Range("fromtoflow").Value
The data gets pulled in, but it looks like this:
(tried a pic, but I'm a new user)
Item 1
Item 1(1)
Item 1 (1,1) 1
Item 1 (1,2) 2
Item 1 (1,3) 4
So it shows that the Collection has 1 item instead of my # of arcs. How do I access the Item1(1,2) type address for the collection. Does each special value have a unique key? How do I search through my collection and remove a specific row after I've used it in the code?
THANK YOU SO MUCH FOR ANY HELP.
After much trial and error, I've decided to make my original data an array and search it like this (d is down the array, a is across):
For d = LBound(arcflow(), 1) To UBound(arcflow(), 1)
For a = LBound(arcflow(), 2) To UBound(arcflow(), 2)
If a = 1 Then
fromnode = arcflow(d, a)
ElseIf a = 2 Then
tonode = arcflow(d, a)
ElseIf a = 3 Then
flow = arcflow(d, a)
'write into node-node matrix
Sheets("FlowDecomp_Solve").Range("nodenodemtrx").Cells(fromnode, tonode).value = 1
End If
Next a
Next d
Then to trace the path, I add the from and to nodes to a collection called Path until it can't find another arc and I write the path out, empty the collection, update the values, and start again.
Hope this helps someone else...

Extract substring of list based on another list

Using two lists, one consisting of names with added information in various forms (see below for example - list 1) and one consisting of the clear formatted names, i.e. with no added information (list 2)
List 1
--------
Netto City | Value
Imerco City | value
Bilka Suburb | value
Bauhaus, City | Value
City FDB Superb | Value
List 2
------
Netto
Imerco
Bilka
Bauhaus
FDB Super
What I am trying to do is create a filter, so that no matter what the first column of my source data(list 1) looks like, i will be able to sum the values based on (list 2).
Something similar to this: Excel - extracting data based on another list
I tried using vlookup, but that does not search for substrings, then i tried using
=IF(COUNTIF(A$4:A$9;"*"&D5&"*")>0;
INDIRECT(ADDRESS(MATCH("*"&D5&"*";A$4:A$9;0);4));"not found")
But that appears to do the opposite, search list 1 for a single cell value from list 2.
I can't quite get my head around if this works just as well, I havent been able to get it to work anyway, thus my search for the other way. Search List 2, for each item from List 1.
But, ultimately, what I am trying to accomplish is to create a list from the source data, which I can use to categorize each item in list 1 from, based on list 3
List 3
Bilka | Cat1
Imerco | Cat2
FDB Super | Cat1
etc.
For that to work, i need a clean list of the source data, without all the extra information which comes with it.
I use the following sumif
=SUMIFS($F$3:$F$703;$B$3:$B$703;
"="&$H4;$D$3:$D$703;">="&I$2;$D$3:$D$703;"<="&I$3)
to sum all sums belonging to a particular item in List 3 (where i've manually created List 3), between to dates.
The purpose of this is to create a sheet that contains all expenditures to a particular store or category of ones own choosing, for instance the ones listed in List 1, are primarily food stores.
Edit - Clarification.
What I am proposing to do is a multistage process.
Stage 1:
Insert original source data (done)
Stage 2:
Filter source data for unique values (done)
Stage 3:
Create list of approve names for each item in source data
- Ie, Bilka Suburb into Bilka, Netto City into Netto
Here 'Netto' and 'Bilka' are approved names which is manually created to allow for grouping in stage 4. I am looking to automatize this step.
Stage 4:
Group each item from the list of Stage 3, based on name and date-interval, weekly monthly whatever (done) if i could only get Stage 3 to work, as it works on my manually corrected data.
Stage 5:
Select appropriate category, and type for each item in resulting list from Stage 3:
Bilka, is a food place, so it would get the category 'food', same as netto, where Bauhaus would get the category 'Building Supplies', each of these items would get the type 'expense' where say wage would get the type 'income' (done)
the solution to stage 5, is just a vlookup, based on the category into a table that lists each category with a type, so that is simple enough.
Final Solution: Requires that the list to iterate over is in column G, and outputs the list of approved names in column H. There is the error of if not being able to know the difference between an item such as "Super" and "SU", I don't know how to fix that. If anyone has any suggestions on that I am all ears.
Sub LoopCells()
Sheets("RawData").Select
Sheets("RawData").Activate
LRApproved = Cells(Rows.Count, "H").End(xlUp).Row
LRsource = Cells(Rows.Count, "G").End(xlUp).Row
For Each approvedcell In Worksheets("RawData").Range("H2:H" & LRApproved).Cells 'Approved stores entered by users
For Each sourcecell In Worksheets("RawData").Range("G2:G" & LRsource).Cells 'items found from bank statement export
If InStr(UCase(sourcecell.Value), UCase(approvedcell.Value)) <> 0 Then
sourcecell.Offset(0, 2).Value = approvedcell.Value
End If
Next sourcecell
Next approvedcell
End Sub
Thanks for all the help.
Edit: Added final solution and VBA tag.
This works for me:
=SUM(B$3:B$7*NOT(ISERROR(SEARCH(A11,A$3:A$7))))
This assumes that your example list 1 is in range A3:B7 and your list 2 in A11:B15. Paste the above formula in cell B11 and press CtrlShift-Enter to enter it as an array formula. Then you can drag-copy it all the way down to B15.
Explanation: SEARCH for e.g. "Netto" in the cells of List 1. For cells that do not contain that string, SEARCH returns an error. So we're looking for cells that do not return an error. We now have an array of booleans indicating this. Multiply it element-by-element by the array of values. In this multiplication, TRUE is interpreted as 1 and FALSE as zero, so you're screening out the values that don't correspond to "Netto".
Here's a secreenshot of my setup:
Perhaps I've misunderstood but can't you use SUMIF?
=SUMIF(A$4:A$9;"*"&D5&"*";B$4:B$9)
instead of going with VBA, you can extract this with simple small formula. =Index(List2!A2:A10,Match(1,Countif(List1A2,""&List2!A2:A10&""),0)) (Press Ctrl+Shift+Enter). Assume you want to extract the list 2 in to list 1.