SharePoint 2010 "foreach" - sharepoint-2010

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

Related

MsProject: Set Baseline for a big number of tasks

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

TFS query on HTML-field for empty value

I want to get with a wiql query all workitem that have an empty HTML field.
Is there a way to do so?
To query out those work items who have empty HTML field like Description, using the query from TFS web page couldn't do that. There's no operator like "isEmpty or isNotEmpty" to use. Here is a uservoice about your request, and according to it, this feature is under review now.
As a workaround, you could use Excel to filter those work items. Write a simple query and export those work items to Excel. Then use the filter In Excel.
You could also use TFS object model api to get those empty field workitems, here is an example:
WorkItemStore workItemStore = teamProjectCollection.GetService<WorkItemStore>();
string queryString = "Select [State], [Title],[Description] From WorkItems Where [Work Item Type] = 'User Story' and [System.TeamProject] = 'TeamProjectName'";
// Create and run the query.
Query query = new Query(workItemStore, queryString);
WorkItemCollection witCollection = query.RunQuery();
foreach (WorkItem workItem in witCollection)
{
//check if the field is empty
if(workItem.Fields["Description"].Value.ToString() == string.Empty || workItem.Fields["Description"].Value.ToString() == "")
{
Console.WriteLine(workItem.Title);
}
}

Why aren't my Sharepoint List contents being saved to the list?

I'm successfully creating a Sharepoint List (named "XMLToPDFTestList"), which I can see via Site Actions > View All Site Content, but my attempts to add columns to the list has so far proven fruitless.
Here is how I'm trying to do it:
private void ProvisionallyCreateList()
{
SPWeb mySite = SPContext.Current.Web;
// Check to see if list already exists; if so, exit
if (mySite.Lists.TryGetList(listTitle) != null) return;
SPListCollection lists = mySite.Lists;
SPListTemplateType listTemplateType = new SPListTemplateType();
listTemplateType = SPListTemplateType.GenericList;
string listDescription = "This list is to hold inputted vals";
lists.Add(listTitle, listDescription, listTemplateType);
// Now add a couple of columns
SPList list = lists["XMLToPDFTestList"];
string faveNum = list.Fields.Add("favoriteNumber", SPFieldType.Text, false);
list.Fields[faveNum].Description = "favorite number";
list.Fields[faveNum].Update();
string faveCol = list.Fields.Add("favoriteColor", SPFieldType.Text, false);
list.Fields[faveCol].Description = "favorite color";
list.Fields[faveCol].Update();
}
This is all I see when I click "XMLToPDFTestList":
My "gut feeling" is that this line:
SPList list = lists["XMLToPDFTestList"];
...is not right/not specific enough. Instead of "XMLToPDFTestList" it should be something else/prepend something, or so. But what, exactly?
It was, as is so often the case, "my bad" (YMMV?).
The problem is in my list item creation code which, because I was not assigning anything to the default/inherited "Title" field, made it appear to me (as in the scream shot above) that no item was being added.
Once I fixed the code, by changing this:
private void SaveInputToList()
{
using (SPSite site = new SPSite(siteUrl))
{
using (SPWeb web = site.RootWeb)
{
SPList list = web.Lists[listTitle];
SPListItem SPListItemFaveNum = list.Items.Add();
SPListItemFaveNum["favoriteNumber"] = "7"; //inputtedNumber; TODO: Once 7 and teal are being saved and retrieved successfully, assign the var vals - will need to declare the controls created in CreateChildControls() globally
SPListItemFaveNum.Update();
SPListItem SPListItemFaveHue = list.Items.Add();
SPListItemFaveHue["favoriteColor"] = "teal";
SPListItemFaveHue.Update();
}
}
}
...to this:
private void SaveInputToList()
{
using (SPSite site = new SPSite(siteUrl))
{
using (SPWeb web = site.RootWeb)
{
SPList list = web.Lists[listTitle];
SPListItem spli = list.Items.Add();
spli["Title"] = "Write the Title";
spli["favoriteNumber"] = "7";
//SPListItemFaveNum.Update();
//SPListItem SPListItemFaveHue = list.Items.Add();
spli["favoriteColor"] = "teal";
//SPListItemFaveHue.Update();
spli.Update();
}
}
}
...it works fine: an item is added with all three values (Title, favoriteNumber, and favoriteColor).
I was assuming the item wasn't being created because "Title" was blank, and I was calling update on each SPListItem, whereas all I really need to do is call Update once, and on one SPListItem, not multiple.

Get the lookup field value for a list item in SharePoint 2010 using C#

I am relatively new to sharepoint and I'm trying to write a web service to return our sharepoint inventory data as xml. It works good except that one of those list includes a lookup field and the generated xml contains "Microsoft.SharePoint.Client.FieldLookupValue" instead of the expected string value of the lookup field.
This is the code I'm using to generate the xml:
resultList = remoteWeb.Lists.GetByTitle("Cam Devices");
context.Load(resultList);
context.ExecuteQuery();
//Now its time to reach list's items
items = resultList.GetItems(new CamlQuery());
context.Load(items);
context.ExecuteQuery();
foreach (ListItem item in items)
{
rootNode.AppendChild(doc.CreateElement("ID")).InnerText = "pcat:401824";
rootNode.AppendChild(doc.CreateElement("Category")).InnerText = "Cam Devices";
rootNode.AppendChild(doc.CreateElement("Kimlik")).InnerText = Convert.ToString(item["ID"]);
rootNode.AppendChild(doc.CreateElement("Isim")).InnerText = Convert.ToString(item["Location0"]) + " >> " + Convert.ToString(item["Brand"]) + " >> " + Convert.ToString(item["ID"]);
}
item["Location"] is the lookup field and it has a value with the type FieldLookupValue, how can I get the lookup value as a string?
Ok, successfully get the lookup field's value by using following code syntax:
string Location = "";
if (item["Location0"] != null)
{
var fl = (SPFieldLookupValue)item["Location0"];
Location = fl.LookupValue;
}

Export SQL query data to Excel

I have a query that returns a very large data set. I cannot copy and paste it into Excel which I usually do. I have been doing some research on how to export directly to an Excel sheet. I am running SQL SERVER 2008 on a server running Microsoft Server 2003. I am trying to use the Microsoft.Jet.OLEDB.4.0 data provider and Excel 2007. I've pieced together a small piece of code that looks like this from what I've seen in examples.
INSERT INTO OPENDATASOURCE('Microsoft.Jet.OLEDB.4.0',
'Data Source=C:\Working\Book1.xlsx;Extended Properties=EXCEL 12.0;HDR=YES')
SELECT productid, price FROM dbo.product
However this is not working, I am getting an error message saying
"Incorrect syntax near the keyword 'SELECT'".
Does anyone have any ideas about how to do this or possibly a better approach?
I don't know if this is what you're looking for, but you can export the results to Excel like this:
In the results pane, click the top-left cell to highlight all the records, and then right-click the top-left cell and click "Save Results As". One of the export options is CSV.
You might give this a shot too:
INSERT INTO OPENROWSET
('Microsoft.Jet.OLEDB.4.0',
'Excel 8.0;Database=c:\Test.xls;','SELECT productid, price FROM dbo.product')
Lastly, you can look into using SSIS (replaced DTS) for data exports. Here is a link to a tutorial:
http://www.accelebrate.com/sql_training/ssis_2008_tutorial.htm
== Update #1 ==
To save the result as CSV file with column headers, one can follow the steps shown below:
Go to Tools->Options
Query Results->SQL Server->Results to Grid
Check “Include column headers when copying or saving results”
Click OK.
Note that the new settings won’t affect any existing Query tabs — you’ll need to open new ones and/or restart SSMS.
If you're just needing to export to excel, you can use the export data wizard.
Right click the database, Tasks->Export data.
I had a similar problem but with a twist - the solutions listed above worked when the resultset was from one query but in my situation, I had multiple individual select queries for which I needed results to be exported to Excel. Below is just an example to illustrate although I could do a name in clause...
select a,b from Table_A where name = 'x'
select a,b from Table_A where name = 'y'
select a,b from Table_A where name = 'z'
The wizard was letting me export the result from one query to excel but not all results from different queries in this case.
When I researched, I found that we could disable the results to grid and enable results to Text. So, press Ctrl + T, then execute all the statements. This should show the results as a text file in the output window. You can manipulate the text into a tab delimited format for you to import into Excel.
You could also press Ctrl + Shift + F to export the results to a file - it exports as a .rpt file that can be opened using a text editor and manipulated for excel import.
Hope this helps any others having a similar issue.
For anyone coming here looking for how to do this in C#, I have tried the following method and had success in dotnet core 2.0.3 and entity framework core 2.0.3
First create your model class.
public class User
{
public string Name { get; set; }
public int Address { get; set; }
public int ZIP { get; set; }
public string Gender { get; set; }
}
Then install EPPlus Nuget package. (I used version 4.0.5, probably will work for other versions as well.)
Install-Package EPPlus -Version 4.0.5
The create ExcelExportHelper class, which will contain the logic to convert dataset to Excel rows. This class do not have dependencies with your model class or dataset.
public class ExcelExportHelper
{
public static string ExcelContentType
{
get
{ return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; }
}
public static DataTable ListToDataTable<T>(List<T> data)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
DataTable dataTable = new DataTable();
for (int i = 0; i < properties.Count; i++)
{
PropertyDescriptor property = properties[i];
dataTable.Columns.Add(property.Name, Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType);
}
object[] values = new object[properties.Count];
foreach (T item in data)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = properties[i].GetValue(item);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
public static byte[] ExportExcel(DataTable dataTable, string heading = "", bool showSrNo = false, params string[] columnsToTake)
{
byte[] result = null;
using (ExcelPackage package = new ExcelPackage())
{
ExcelWorksheet workSheet = package.Workbook.Worksheets.Add(String.Format("{0} Data", heading));
int startRowFrom = String.IsNullOrEmpty(heading) ? 1 : 3;
if (showSrNo)
{
DataColumn dataColumn = dataTable.Columns.Add("#", typeof(int));
dataColumn.SetOrdinal(0);
int index = 1;
foreach (DataRow item in dataTable.Rows)
{
item[0] = index;
index++;
}
}
// add the content into the Excel file
workSheet.Cells["A" + startRowFrom].LoadFromDataTable(dataTable, true);
// autofit width of cells with small content
int columnIndex = 1;
foreach (DataColumn column in dataTable.Columns)
{
int maxLength;
ExcelRange columnCells = workSheet.Cells[workSheet.Dimension.Start.Row, columnIndex, workSheet.Dimension.End.Row, columnIndex];
try
{
maxLength = columnCells.Max(cell => cell.Value.ToString().Count());
}
catch (Exception) //nishanc
{
maxLength = columnCells.Max(cell => (cell.Value +"").ToString().Length);
}
//workSheet.Column(columnIndex).AutoFit();
if (maxLength < 150)
{
//workSheet.Column(columnIndex).AutoFit();
}
columnIndex++;
}
// format header - bold, yellow on black
using (ExcelRange r = workSheet.Cells[startRowFrom, 1, startRowFrom, dataTable.Columns.Count])
{
r.Style.Font.Color.SetColor(System.Drawing.Color.White);
r.Style.Font.Bold = true;
r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
r.Style.Fill.BackgroundColor.SetColor(Color.Brown);
}
// format cells - add borders
using (ExcelRange r = workSheet.Cells[startRowFrom + 1, 1, startRowFrom + dataTable.Rows.Count, dataTable.Columns.Count])
{
r.Style.Border.Top.Style = ExcelBorderStyle.Thin;
r.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
r.Style.Border.Left.Style = ExcelBorderStyle.Thin;
r.Style.Border.Right.Style = ExcelBorderStyle.Thin;
r.Style.Border.Top.Color.SetColor(System.Drawing.Color.Black);
r.Style.Border.Bottom.Color.SetColor(System.Drawing.Color.Black);
r.Style.Border.Left.Color.SetColor(System.Drawing.Color.Black);
r.Style.Border.Right.Color.SetColor(System.Drawing.Color.Black);
}
// removed ignored columns
for (int i = dataTable.Columns.Count - 1; i >= 0; i--)
{
if (i == 0 && showSrNo)
{
continue;
}
if (!columnsToTake.Contains(dataTable.Columns[i].ColumnName))
{
workSheet.DeleteColumn(i + 1);
}
}
if (!String.IsNullOrEmpty(heading))
{
workSheet.Cells["A1"].Value = heading;
// workSheet.Cells["A1"].Style.Font.Size = 20;
workSheet.InsertColumn(1, 1);
workSheet.InsertRow(1, 1);
workSheet.Column(1).Width = 10;
}
result = package.GetAsByteArray();
}
return result;
}
public static byte[] ExportExcel<T>(List<T> data, string Heading = "", bool showSlno = false, params string[] ColumnsToTake)
{
return ExportExcel(ListToDataTable<T>(data), Heading, showSlno, ColumnsToTake);
}
}
Now add this method where you want to generate the excel file, probably for a method in the controller. You can pass parameters for your stored procedure as well. Note that the return type of the method is FileContentResult. Whatever query you execute, important thing is you must have the results in a List.
[HttpPost]
public async Task<FileContentResult> Create([Bind("Id,StartDate,EndDate")] GetReport getReport)
{
DateTime startDate = getReport.StartDate;
DateTime endDate = getReport.EndDate;
// call the stored procedure and store dataset in a List.
List<User> users = _context.Reports.FromSql("exec dbo.SP_GetEmpReport #start={0}, #end={1}", startDate, endDate).ToList();
//set custome column names
string[] columns = { "Name", "Address", "ZIP", "Gender"};
byte[] filecontent = ExcelExportHelper.ExportExcel(users, "Users", true, columns);
// set file name.
return File(filecontent, ExcelExportHelper.ExcelContentType, "Report.xlsx");
}
More details can be found here
I see that you’re trying to export SQL data to Excel to avoid copy-pasting your very large data set into Excel.
You might be interested in learning how to export SQL data to Excel and update the export automatically (with any SQL database: MySQL, Microsoft SQL Server, PostgreSQL).
To export data from SQL to Excel, you need to follow 2 steps:
Step 1: Connect Excel to your SQL database‍ (Microsoft SQL Server, MySQL, PostgreSQL...)
Step 2: Import your SQL data into Excel
The result will be the list of tables you want to query data from your SQL database into Excel:

Step1: Connect Excel to an external data source: your SQL database
Install An ODBC
Install A Driver
Avoid A Common Error
Create a DSN
Step 2: Import your SQL data into Excel
Click Where You Want Your Pivot Table
Click Insert
Click Pivot Table
Click Use an external data source, then Choose Connection
Click on the System DSN tab
Select the DSN created in ODBC Manager
Fill the requested username and password
Avoid a Common Error
Access The Microsoft Query Dialog Box
Click on the arrow to see the list of tables in your database
Select the table you want to query data from your SQL database into Excel
Click on Return Data when you’re done with your selection
To update the export automatically, there are 2 additional steps:
Create a Pivot Table with an external SQL data source
Automate Your SQL Data Update In Excel With The GETPIVOTDATA Function
I’ve created a step-by-step tutorial about this whole process, from connecting Excel to SQL, up to having the whole thing automatically updated. You might find the detailed explanations and screenshots useful.