MsProject: Set Baseline for a big number of tasks - vsto

I'm working on a a small addin which allows me to edit set my baseline depending of a SQL request.
This is my current code:
foreach (ReturnEnumTasks i_objsectionTask in l_objTaskList)
{
MSProject.Task l_objTaskSection = taskManagement.getTask(l_objProject, new Guid(i_objsectionTask.taskUID));
if (l_objTaskSection != null)
{
foreach (MSProject.Task i_objTask in g_objProject.Tasks)
{
if (!i_objTask.Summary)
{
if (i_objTask.OutlineNumber.like(l_objTaskSection.OutlineNumber + "%"))
{
baselineManagement.setBaseline(l_objProject, i_objTask, m_objBaselineNumber);
baselineManagement.setBaseline(l_objProject, i_objTask, baselineNumber.baseline0);
}
}
}
}
}
So this is the idea, I have a SQL query which returns me the the tasks with a special wbs
After that, I convert these strings into Tasks object with a function I built.
Once, it's done I set my baseline for the task.
The problem is the following if, I have 100 tasks, my addin took more than 30 seconds to do the calculation.
So I'd like to know if there is a way to select all of my tasks and store them in Tasks object and after that make one setbaseline for the whole selection
Because I made some trials and apparently it's better to select all the tasks and set the baseline than to set the baseline one by one

Related

SSIS Import data that is NOT columnar into SQL

I am fairly new to SSIS and need a little help getting started. I have several reports that come out of our mainframe. The reports are not in a columnar format. The date record is at the top then there might be some initial data then there might be a little more. So I need to read in each line look to see what the text reads and figure out if I need the data or move to the next row.
This is a VERY rough example of what the report I want to import into a SQL table.
DATE: 01/08/2020 FACILITY NAME PAGE1
REVENUE USAGE FOR ACCOUNTING PERIOD 02
----TOTAL---- ----TOTAL---- ----OTHER---- ----INSURANCE---- ----INSURANCE2----
SERVICE CODE - 123456789 DESCRIPTION: WIDGETS
CURR 2,077
IP 0.0000 3 2,345 0.00
143
OP 0.0000 2 1,231 0.00
YTD 5
IP 0.0000
76
OP 0.0000
etc . . . .. .
SERVICE CODE
After the SERVICE CODE the data will start to repeat like it is above. This is the basic idea of a report.
I want to get the Date then the Service Code, Description, Current IP Volume, Current IP Dollar, Current OP Volume, Current OP Dollar, YTD IP Volume, YTD IP Dollar, YTD OP Volume, YTD OP Dollar . . then repeat.
Just to clarify, I am not asking anyone to do this for me. I want to learn how to do this. I have looked on how to do this but every example I have looked at talks about doing this with a CSV, tab, or Excel file. i do not have that type of file so I was asking what I need to look at. I currently use Monarch to format the file, but again I want to learn more about SSIS and this is a perfect way to learn. Asking the vendor to redo the report is not an option plus I want to learn how to do this. Thank you I just wanted to get that out there.
Any help would be greatly appreciated.
Rodger
As stated in comments, you could do this using a script task. The basics steps are:
Define a DataTable to store your data.
Use a StreamReader to read your report.
Process this using a combination of conditionals, String Methods, and parsing to extract the relevant fields from the relevant line:
Write the DataTable to the database using SqlBulkCopy
The following would go inside your Main method in your script task:
//Define a table to store your data
var table = new DataTable
{
Columns =
{
{ "ServiceCode", typeof(string) },
{ "Description", typeof(string) },
{ "CurrentIPVolume", typeof(int) },
{ "CurrentIPDollar,", typeof(decimal) },
{ "CurrentOPVolume", typeof(int) },
{ "CurrentOPDollar", typeof(decimal) },
{ "YTDIPVolume", typeof(int) },
{ "YTDIPDollar,", typeof(decimal) },
{ "YTDOPVolume", typeof(int) },
{ "YTDOPDollar", typeof(decimal) }
}
};
var filePath = #"Your File Path";
using (var reader = new StreamReader(filePath))
{
string line = null;
DataRow row = null;
// As YTD and Curr are identical, we will need a flag later to mark our position within the record
bool ytdFlag= false;
//Loop through every line in the file
while ((line = reader.ReadLine()) != null)
{
//if the line is blank, move on to the next
if (string.IsNullOrWhiteSpace(line)
continue;
// If the line starts with service code, then it marks the start of a new record
if (line.StartsWith("SERVICE CODE"))
{
//If the current value for row is not null then this is
//not the first record, so we need to add the previous
//record to the tale before continuing
if (row != null)
{
table.Rows.Add(row);
ytdFlag= false; // New record, reset YTD flag
}
row = table.NewRow();
//Split the line now based on known values:
var tokens = line.Split(new string[] { "SERVICE CODE - ", "DESCRIPTION: "}, StringSplitOptions.None);
row[0] = tokens[0];
row[1] = tokens[1];
}
if (line.StartsWith("CURR"))
{
//Process the row --> "CURR 2,077"
//Not sure what 2,077 is, but this will parse it
int i = 0;
if (int.TryParse(line.Substring(4).Trim().Replace(",", ""), out i))
{
//Do something with your int
Console.WriteLine(i);
}
}
if (line.StartsWith(" IP"))
{
//Start at after IP then split the line into the 4 numbers
var tokens = line.Substring(3).Split(new [] { " "}, StringSplitOptions.RemoveEmptyEntries);
//If we have gone past the CURR record, then at to YTD Columns
if (ytdFlag)
{
row[6] = int.Parse(tokens[1]);
row[7] = decimal.Parse(tokens[1]);
}
//Otherwise we are still in the CURR section:
else
{
row[2] = int.Parse(tokens[1]);
row[3] = decimal.Parse(tokens[1]);
}
}
if (line.StartsWith(" OP"))
{
//Start at after OP then split the line into the 4 numbers
var tokens = line.Substring(3).Split(new [] { " "}, StringSplitOptions.RemoveEmptyEntries);
//If we have gone past the CURR record, then at to YTD Columns
if (ytdFlag)
{
row[8] = int.Parse(tokens[1]);
row[9] = decimal.Parse(tokens[1]);
}
//Otherwise we are still in the CURR section:
else
{
row[4] = int.Parse(tokens[1]);
row[5] = decimal.Parse(tokens[1]);
}
//After we have processed an OP record, we must set the YTD Flag to true.
//Doesn't matter if it is the YTD OP record, since the flag will be reset
//By the next line that starts with SERVICE CODE anyway
ytdFlag= true;
}
}
}
//Now that we have processed the file, we can write the data to a database
using (var sqlBulkCopy = new SqlBulkCopy("Your Connection String"))
{
sqlBulkCopy.DestinationTableName = "dbo.YourTable";
//If necessary add column mappings, but if your DataTable matches your database table
//then this is not required
sqlBulkCopy.WriteToServer(table);
}
This is a very quick example, far from the finished article, and I have done little or no testing, but it should give you the gist of how it could be done, and get you started on one possible solution.
It can definitely be cleaned up and refactored, but I have tried to make it as clear as possible what is going on, rather than trying to write the most efficient code ever. It should also (hopefully) demonstrate what a monumental pain this is to do, and very minor report changes things like an extra space be "OP" will break the whole thing.
So again, I would re-iterate, if you can get the data in a standard flat file format, with one line per record, you should. I do however appreciate that sometimes these things are out of your control, and I have had to write incredibly ugly import routines like this in the past, so I feel your pain if you can't get the data in a consumable format.

How to speed up row deleting function in Google App Script

I'm trying to run through a few hundred rows of data and delete rows that have 0 in both C and D. Deleting the ones that match that case seems to be working, but it really takes its time getting through. I'm a neophyte at scripting (I'm not a programmer, just trying to learn) and I can't figure how to make it faster. The main script came from someone else, I added the logic to do two columns and not just one. Any Ideas?
function deleteZeroes() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Email_Help_Total_Input');
var range1 = s.getRange('C:C');
var cValues = range1.getValues();
var range2 = s.getRange('D:D');
var dValues = range2.getValues();
for(var i=cValues.length-1;i>=0;i--)
if(cValues[0,i]==0 && dValues[0,i]== 0)
s.deleteRow(i+1);
}
It works, but slowly. Just trying to make it a little quicker. Thanks!
Array rather than reads and writes!
data = s.getDataRange().getValues();
result = [];
for (i=0;i<data.length;i++) {
if (data[i][2]==0) continue; //checks C, if it finds it continues the loop
if (data[i][3]==0) continue; //checks D, if it finds it continues the loop
result.push(data[i]);//only those that fell through the 0 checks will be here
}
s.getDataRange().clear();
s.getRange(1,1,result.length,result[0].length).setValues(result);
So this reads all the data at once, checks all the data and copies the good rows to a new result array, deletes the old data and then pastes back the good data. Depending on the size you should see this function in maybe 30 seconds.

Why Cronjob (Qunatz scheduler) is generating duplicates?

In my application for generating a unique no I am using a Quartz scheduler Cronjob (I had to use Cronjob because no manual intervention is there to generating that no).
But some how it had generated unique no for some time after that I found that No. duplicating then when I check the log file of my jboss server
I found this
2014-04-16 00:29:00,164 INFO [IportLogger] (DefaultQuartzScheduler_Worker-9) =======update Doc Series of FIRSTWGT weight ===The next no we get here is =================76
2014-04-16 08:52:00,189 INFO [IportLogger] (DefaultQuartzScheduler_Worker-7) =======updateDocSeries of FIRSTWGT weight ===The next no we get here is =================76
how this happened ?
Same no has generated 2 times at 2 different times ?
I'm using struts 2 and jpa 2 and sql server as my database.
Anyone can give me a hint about this???
There may be N no of transaction tables are in the project , each transaction will be identified by it's "doc series code", and for that particular table if user post a transaction successfully I will allocate transaction No from doc series table where it will maintain a variable called "next No" for that particular series and it will be incremented manually each time when a transaction is posted by user,
here in my case i am allocating the unique no by cronjob, by increment the "Next No" each time please observe the following code
FirstWeight firstWeight=new FirstWeight();
IptDocumentseries ids = dochelper.getDocSeriesNo("FIRSTWGT"); // FIRSTWGT is doc series for a table called first weight
Long nextno = ids.getNextNo();
//System.out.println("value of doc no." +nextno);
firstWeight.setDocNum(nextno);
firstWeight.setDocStatus("Approved");
FWDao.update(firstWeight);//saving into database
dochelper.updateDocSeries("FIRSTWGT",firstWeight.getDocSeriesCode());
public synchronized void updateDocSeries(String doccode,String docseries)
{
Long nextno= 0L;
List<IptDocumentseries> idslist =iidsd.findByDocSeriesCode(doccode,docseries);
try{
System.out.println("The List size of the idslist is : "+idslist.size());
if(idslist!=null && !idslist.isEmpty())
{
System.out.println("The List size of the idslist is inside if : "+idslist.size());
nextno = idslist.get(0).getNextNo();
IptDocumentseries ids = new IptDocumentseries();
ids = idslist.get(0);
ids.setNextNo(++nextno);
IportLogger.log("=======updateDocSeries===The next no we get here is ================="+ nextno);
if(doccode.equalsIgnoreCase("FIRSTWGT"))
{
Logger.log("=======updateDocSeries of FIRSTWGT weight ===The next no we get here is ================="+ nextno);
}
ids.setModifiedDate(getCurrentTimeStamp());
System.out.println("The next no we get here is "+ nextno);
iidsd.update(ids);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}

How to query an index with a subcollection that has date ranges in RavenDB?

I prepared the full test case here: https://gist.github.com/pkrakowiak/cc8addf5725193a01f2d
There are Location documents. Each location can have zero or more sponsors during some time periods (represented by the IList<Sponsorship> Sponsors property). I need to return only those locations that are sponsored on a particular day (say 15th of March in my example). So such location must have at least one Sponsorship instance that matches the following query: .Where(x => x.Sponsors.Any(s => s.From <= today && s.To >= today))
I prepared two tests, one is not using an index explicitly: CanGetCurrentlySponsoredLocations, and one which uses a static index that I created: CanGetCurrentlySponsoredLocationsUsingStaticIndex. The first one will pass, the second one will fail. The question is - how do I make the second test pass? What sort of modifications do I need to apply to my Locations_ByCoordinates index?
In case you are wondering where the index name came from or what the reviews are - just ignore them. :) They are leftovers from other things that I was testing.
Update
I took this question first to the official RavenDB Google group: https://groups.google.com/forum/?fromgroups=#!topic/ravendb/ySUPXqkpTA8 Sadly, it did not bring me a solution.
The simplest index that will pass your unit test is:
private class Locations_ByCoordinates : AbstractIndexCreationTask<Location>
{
public Locations_ByCoordinates()
{
Map = locations => from l in locations
from s in l.Sponsors
select new
{
Sponsors_From = s.From,
Sponsors_To = s.To
};
}
}
You might want to pick a better name, since the coordinates aren't indexed.
I'm not sure what your other test CanSortOnSponsorshipStatus is all about though.
UPDATE
To include locations that have no sponsors, use the DefaultIfEmpty linq extension method. This will make sure that all locations have at least one index entry.
private class Locations_ByCoordinates : AbstractIndexCreationTask<Location>
{
public Locations_ByCoordinates()
{
Map = locations => from l in locations
from s in l.Sponsors
.DefaultIfEmpty(new Sponsorship
{
From = DateTime.MinValue,
To = DateTime.MaxValue
})
select new
{
Sponsors_From = s.From,
Sponsors_To = s.To
};
}
}

SharePoint 2010 "foreach"

I have 2 SharePoint lists, and I have to copy all items from List1 to List2.
On List1 there is a boolean field (defaults to 'no'), a text field and an associated WorkFlow which triggers on modifications.
The WokFlow simplified:
Copy current item to List2
Set my boolen field to 'yes'
Search for an item with boolen field 'no', set its text field to 'copy'
I start the process by modifing an item in List1, then it will copy itself to List2, modifies an another item, and so on... until there is any item with a boolen field set to 'no'.
This works perfectly for 10 items, but then it fails. Item 10 modified item 11's text field to 'copy', but item 11's WorkFlow does not started. I've tried it serval times, and always stopped after 10 copies.
I've Googled and MSDN'd. The best solution I've found is to pause for 1 minute in the WorkFlow. But I have thousands of items...
Has anyone any advice? I even cant find any limit in the SharePoint 2010 server that defaults to 10.
Thank You!
You are triggering a hardcoded resource throttle in SharePoint 2010 due to the speed on the workflow. It's there to prevent the system from becoming unresponsive during workflow operations. Code in an application page or timer job will get around this limit but it's not recommended to have a greedy operation that cause the system to become unresponsive to users.
You can do CAML batch methods.
somethig like this:
void UpdateList()
{
StringBuilder methodBuilder = new StringBuilder();
string batch = string.Empty;
string newValue="mmmm";
string updateColumn = "SampleColumn";
try
{
string batchFormat = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<ows:Batch OnError=\"Continue\">{0}</ows:Batch>";
string methodFormat = "<Method ID='{0}' >" +
"<SetList>{1}</SetList>" +
"<SetVar Name='Cmd'>Save</SetVar>" +
"<SetVar Name='ID'>{2}</SetVar>" +
"<SetVar Name='urn:schemas-microsoft-com:office:office#{3}'>{4}</SetVar>" +
"</Method>";
using (SPSite siteCol = new SPSite("SampleSite"))
{
using (SPWeb web = siteCol.OpenWeb())
{
// Get the list containing the items to update
SPList list = web.Lists["SampleList"];
string listGuid = list.ID.ToString();
SPListItemCollection allItems = list.GetItems();
// Build the CAML update commands.
for (int i = 0; i < allItems.Count; i++)
{
int itemID = allItems[i].ID;
methodBuilder.AppendFormat(methodFormat, itemID, listGuid, itemID, updatedColumn, newValue);
}
web.AllowUnsafeUpdates = true;
// Generate the CAML
batch = string.Format(batchFormat, methodBuilder.ToString());
// Process the batch
string batchReturn = web.ProcessBatchData(batch);
}
//done
}
}
catch (Exception ex)
{
//show the error
}
}
You can create batch methods for create , delete and update items on lists and document libraries.
Refs:
http://msdn.microsoft.com/en-us/library/office/ms437562%28v=office.15%29.aspx
http://msdn.microsoft.com/en-us/library/office/ms459050(v=office.15).aspx
if you want to change workflow concurrent execution limits ....
For check limits:
Get-SPFarmConfig | Select WorkflowPostponeThreshold
For change
Set-SPFarmConfig -WorkflowPostponeThreshold 50
Timer service process items ( workflows continuations) on batch sizes
Get-SPFarmConfig | Select WorkflowBatchSize
Set-SPFarmConfig -WorkflowBatchSize 150