I ran across the need to dynamically send out 2000+ emails based on a Execute Sql Task in SSIS. I knew I needed to use the For Each Loop Container but wasn't sure how to link multiple rows to a single action in the For Each Loop Container.
I ended up using the Execute Sql Task with a Result Set of "Full result set" and returned the Result Set to a single Variable Object. This allows you to process multiple columns/rows into a single variable. Just need to make sure its a Object variable. Then in the For Each Loop Container Collection I used the Foreach ADO Enumerator. This allowed me to reference the Object variable I setup earlier. Next, I mapped each of the variables in the mapping section based on the order of the columns in the extract proc. Very similar to an array in .net. Finally, I used a script task to fire off an email for each row.
I have used the For Each Loop Containers in the past for processing/imports of data files. This is the first time I have worked with the Object variable in SSIS and agree this is a very power trick to have in your toolbox.
Thanks
Bryan
Thursday, July 29, 2010
Thursday, July 8, 2010
SSRS 2008 Inscope / Percent to Total
Over the past couple of weeks I have been asked several questions about InScope function in SSRS 2008. It is a very useful function that allows for aggergations at different group levels in a report. This is helpful when trying to calculate a dynamic percent to total by a parent group.
Here is an example of how to use Inscope:
Territory Total of 2500 appts
District Total of 125 appts
what is the percent total?
=iif(iif(InScope("Territory", count(Fields!.Appts.Value,"Territory"),0) = 0 , 0,
count(Fields.Appts.Value) / iif(InScope("Territory"), count(Fields.Appts.Value, "Territory"),0))
Result = 5%
Here is an example of how to use Inscope:
Territory Total of 2500 appts
District Total of 125 appts
what is the percent total?
=iif(iif(InScope("Territory", count(Fields!.Appts.Value,"Territory"),0) = 0 , 0,
count(Fields.Appts.Value) / iif(InScope("Territory"), count(Fields.Appts.Value, "Territory"),0))
Result = 5%
Tuesday, June 8, 2010
SharePoint Gantt Chart Formatting
The SharePoint default Gantt chart doesn't provide any formatting but with a Content Editor Web Part and a little bit of CSS you can change the layout and formatt.
What this code does:
- change the images width from 16 to 2 pixels.
- remove the display of weekdays
- rotate the dates to display them vertically
Reference: Link
If you are looking for a zoom slider with JQuery:Link
What this code does:
- change the images width from 16 to 2 pixels.
- remove the display of weekdays
- rotate the dates to display them vertically
Reference: Link
If you are looking for a zoom slider with JQuery:Link
Labels:
Content Query Web Part,
MOSS,
Sharepoint
Thursday, June 3, 2010
Submit InfoPath 2007 with Code (SharePoint list & Email)
Create a SharePoint Library Submit data connection and an Email Submit data connection and then programmatically execute the data connections in the FormEvents_Submit event handler of the InfoPath form, and perform a Close the form action as part of the Submit Options on the InfoPath form.
- In InfoPath, design a browser-compatible InfoPath form template
- On the Data Source task pane, add a Text Field node named formName under the myFields node.
- On the Tools menu, choose Data Connections.
- On the Data Connections dialog box, click Add, and create a new Submit data connection As an e-mail message. Fill in any email address in the To field; you will be changing this in code anyway. Accept the default name of Email Submit for the data connection.
- On the Data Connections dialog box, click Add, and create a new Submit data connection To a document library on a SharePoint site. Fill in a valid URL to a Document Library. Select the formName node from the Main data source to be the File name for the form. Accept the default name of SharePoint Library Submit for the data connection.
- On the Tools menu, choose Submit Options.
- On the Submit Options dialog box, select Allow users to submit this form, deselect the Show the Submit menu item and the Submit toolbar button check box, click Advanced and select Close the form from the After submit drop-down list box, select Perform custom action using Code, and click Edit Code.
- This will add a FormEvents_Submit event handler to the InfoPath form template.
- In Microsoft Visual Studio Tools for Applications, add the following C# code to the FormEvents_Submit event handler:
// Get a reference to the main data source
XPathNavigator root = MainDataSource.CreateNavigator();
// Generate a name for the form to be saved in SharePoint
string formName = Guid.NewGuid().ToString();
// Set the name of the form on the data connection
root.SelectSingleNode(
"//my:formName", NamespaceManager).SetValue(formName);
// Submit the form to SharePoint
DataConnection spConn =
DataConnections["SharePoint Library Submit"];
spConn.Execute();
// Set the properties for the email
string toAddress = root.SelectSingleNode(
"//my:sendTo", NamespaceManager).Value;
EmailSubmitConnection emailConn =
(EmailSubmitConnection)DataConnections["Email Submit"];
emailConn.To.SetStringValue(toAddress);
emailConn.Subject.SetStringValue("This subject was set from code");
emailConn.Introduction = "This email was generated by code.";
emailConn.EmailAttachmentType = EmailAttachmentType.None;
// Send the email
emailConn.Execute();
// Indicate success
e.CancelableArgs.Cancel = false;
Save your work and build the code.
Wednesday, June 2, 2010
Split Comma Delimited String
Andy has put together a really good video on Comma Delimited String parsing in sql. Personally I am a big fan of the CLR functionality on this issue. Make sure to check out the video he has put together.
Link to video:
http://www.sqlshare.com/SplittingDelimitedStrings_774.aspx
Link to Andy's example:
http://www.sqlshare.com/references.774.zip
Here is another example of the split function:
GO
/****** Object: UserDefinedFunction [dbo].[fn_Split] Script Date: 06/02/2010 17:05:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[fn_Split]
(
@sText VARCHAR(8000) ,
@sDelim VARCHAR(20) = ' '
)
RETURNS @retArray TABLE
(
idx SMALLINT PRIMARY KEY ,
value VARCHAR(8000)
)
AS
BEGIN
DECLARE
@idx SMALLINT ,
@value VARCHAR(8000) ,
@bcontinue BIT ,
@iStrike SMALLINT ,
@iDelimlength TINYINT
IF @sDelim = 'Space'
BEGIN
SET @sDelim = ' '
END
SET @idx = 0
SET @sText = LTRIM(RTRIM(@sText))
SET @iDelimlength = DATALENGTH(@sDelim)
SET @bcontinue = 1
IF NOT ( ( @iDelimlength = 0 )
OR ( @sDelim = 'Empty' )
)
BEGIN
WHILE @bcontinue = 1
BEGIN
--If you can find the delimiter in the text, retrieve the first element and
--insert it with its index into the return table.
IF CHARINDEX(@sDelim, @sText) > 0
BEGIN
SET @value = SUBSTRING(@sText, 1,
CHARINDEX(@sDelim,
@sText) - 1)
BEGIN
INSERT @retArray
( idx, value )
VALUES
( @idx, @value )
END
--Trim the element and its delimiter from the front of the string.
--Increment the index and loop.
SET @iStrike = DATALENGTH(@value)
+ @iDelimlength
SET @idx = @idx + 1
SET @sText = LTRIM(RIGHT(@sText,
DATALENGTH(@sText)
- @iStrike))
END
ELSE
BEGIN
--If you can’t find the delimiter in the text, @sText is the last value in
--@retArray.
SET @value = @sText
BEGIN
INSERT @retArray
( idx, value )
VALUES
( @idx, @value )
END
--Exit the WHILE loop.
SET @bcontinue = 0
END
END
END
ELSE
BEGIN
WHILE @bcontinue = 1
BEGIN
--If the delimiter is an empty string, check for remaining text
--instead of a delimiter. Insert the first character into the
--retArray table. Trim the character from the front of the string.
--Increment the index and loop.
IF DATALENGTH(@sText) > 1
BEGIN
SET @value = SUBSTRING(@sText, 1, 1)
BEGIN
INSERT @retArray
( idx, value )
VALUES
( @idx, @value )
END
SET @idx = @idx + 1
SET @sText = SUBSTRING(@sText, 2,
DATALENGTH(@sText) - 1)
END
ELSE
BEGIN
--One character remains.
--Insert the character, and exit the WHILE loop.
INSERT @retArray
( idx, value )
VALUES
( @idx, @sText )
SET @bcontinue = 0
END
END
END
RETURN
END
Link to video:
http://www.sqlshare.com/SplittingDelimitedStrings_774.aspx
Link to Andy's example:
http://www.sqlshare.com/references.774.zip
Here is another example of the split function:
GO
/****** Object: UserDefinedFunction [dbo].[fn_Split] Script Date: 06/02/2010 17:05:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[fn_Split]
(
@sText VARCHAR(8000) ,
@sDelim VARCHAR(20) = ' '
)
RETURNS @retArray TABLE
(
idx SMALLINT PRIMARY KEY ,
value VARCHAR(8000)
)
AS
BEGIN
DECLARE
@idx SMALLINT ,
@value VARCHAR(8000) ,
@bcontinue BIT ,
@iStrike SMALLINT ,
@iDelimlength TINYINT
IF @sDelim = 'Space'
BEGIN
SET @sDelim = ' '
END
SET @idx = 0
SET @sText = LTRIM(RTRIM(@sText))
SET @iDelimlength = DATALENGTH(@sDelim)
SET @bcontinue = 1
IF NOT ( ( @iDelimlength = 0 )
OR ( @sDelim = 'Empty' )
)
BEGIN
WHILE @bcontinue = 1
BEGIN
--If you can find the delimiter in the text, retrieve the first element and
--insert it with its index into the return table.
IF CHARINDEX(@sDelim, @sText) > 0
BEGIN
SET @value = SUBSTRING(@sText, 1,
CHARINDEX(@sDelim,
@sText) - 1)
BEGIN
INSERT @retArray
( idx, value )
VALUES
( @idx, @value )
END
--Trim the element and its delimiter from the front of the string.
--Increment the index and loop.
SET @iStrike = DATALENGTH(@value)
+ @iDelimlength
SET @idx = @idx + 1
SET @sText = LTRIM(RIGHT(@sText,
DATALENGTH(@sText)
- @iStrike))
END
ELSE
BEGIN
--If you can’t find the delimiter in the text, @sText is the last value in
--@retArray.
SET @value = @sText
BEGIN
INSERT @retArray
( idx, value )
VALUES
( @idx, @value )
END
--Exit the WHILE loop.
SET @bcontinue = 0
END
END
END
ELSE
BEGIN
WHILE @bcontinue = 1
BEGIN
--If the delimiter is an empty string, check for remaining text
--instead of a delimiter. Insert the first character into the
--retArray table. Trim the character from the front of the string.
--Increment the index and loop.
IF DATALENGTH(@sText) > 1
BEGIN
SET @value = SUBSTRING(@sText, 1, 1)
BEGIN
INSERT @retArray
( idx, value )
VALUES
( @idx, @value )
END
SET @idx = @idx + 1
SET @sText = SUBSTRING(@sText, 2,
DATALENGTH(@sText) - 1)
END
ELSE
BEGIN
--One character remains.
--Insert the character, and exit the WHILE loop.
INSERT @retArray
( idx, value )
VALUES
( @idx, @sText )
SET @bcontinue = 0
END
END
END
RETURN
END
Thursday, May 27, 2010
InfoPath 2007 Bind Drop Down List with C#.Net
I have seen several ariticles on how to bind a list in InfoPath 2007 so this isn't anything new but I wanted to share the method that worked best for me. I found it best to make a generic method to bind the list so you can hook it into multiple event handlers. This prevented me from writing the same bit of code twice. If you notice prior to binding the list I clear the list. On a prior post I have posted the code for the ClearListBox method. If you don't clear the list prior to you may end up just appending your values.
private void BindDistrictList(string username, string HomeDistrict)
{
string xpListBox = "/my:myFields/my:listDistrict/my:listDistrictItem";
ClearListBox(xpListBox, Root);
try
{
string data = string.Empty;
using (SqlConnection conn = new SqlConnection(_SqlCon))
{
SqlCommand command = new SqlCommand("IPGetDistrictbyUser", conn);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@UserName", SqlDbType.Char).Value = UserName;
command.Parameters.Add("@hd", SqlDbType.Char).Value = HomeDistrict;
conn.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
XmlDocument doc = new XmlDocument();
XmlNode group = doc.CreateElement("listDistrictItem", NamespaceManager.LookupNamespace("my"));
XmlNode field = doc.CreateElement("listDistrictItemName", NamespaceManager.LookupNamespace("my"));
XmlNode node = group.AppendChild(field);
node.InnerText = reader["DistrictName"].ToString();
field = doc.CreateElement("listDistrictItemValue", NamespaceManager.LookupNamespace("my"));
node = group.AppendChild(field);
node.InnerText = reader["DistrictID"].ToString();
doc.AppendChild(group);
MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:listDistrict", NamespaceManager).AppendChild(doc.DocumentElement.CreateNavigator());
}
conn.Close();
}
}
catch (Exception ex)
{
ErrorMessage(ex);
}
}
private void BindDistrictList(string username, string HomeDistrict)
{
string xpListBox = "/my:myFields/my:listDistrict/my:listDistrictItem";
ClearListBox(xpListBox, Root);
try
{
string data = string.Empty;
using (SqlConnection conn = new SqlConnection(_SqlCon))
{
SqlCommand command = new SqlCommand("IPGetDistrictbyUser", conn);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@UserName", SqlDbType.Char).Value = UserName;
command.Parameters.Add("@hd", SqlDbType.Char).Value = HomeDistrict;
conn.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
XmlDocument doc = new XmlDocument();
XmlNode group = doc.CreateElement("listDistrictItem", NamespaceManager.LookupNamespace("my"));
XmlNode field = doc.CreateElement("listDistrictItemName", NamespaceManager.LookupNamespace("my"));
XmlNode node = group.AppendChild(field);
node.InnerText = reader["DistrictName"].ToString();
field = doc.CreateElement("listDistrictItemValue", NamespaceManager.LookupNamespace("my"));
node = group.AppendChild(field);
node.InnerText = reader["DistrictID"].ToString();
doc.AppendChild(group);
MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:listDistrict", NamespaceManager).AppendChild(doc.DocumentElement.CreateNavigator());
}
conn.Close();
}
}
catch (Exception ex)
{
ErrorMessage(ex);
}
}
InfoPath 2007 Clear Databound Drop Down List with C#.Net
Over the past couple weeks I have been working with InfoPath 2007 and cascading drop down list. The issue is once a user decides to go out of the normal flow selection you need to clear the drop down list and re-bind the list. I couldn't find good examples on how to clear a list so I decided to share my code.
Call from your method:
ClearListBox("/my"myFields/my:listLocations/my:listLocationsItem", Root);
Here is the ClearListBox method:
public void ClearListBox(string xp_ListBox, XPathNavigator xNav)
{
//clear list box of items
XPathNodeIterator lstClear = xNav.Select(xp_ListBox, NamespaceManager);
if (lstClear.Count > 0)
{
for (int i = lstClear.Count; i > 0; i--)
{
XPathNavigator reList = MainDataSource.CreateNavigator();
XPathNavigator reListItems = reList.SelectSingleNode(xp_ListBox + "[" + i + "]", NamespaceManager);
reListItems.DeleteSelf();
}
}
}
I am using a Property for Root:
private XPathNavigator Root
{
get
{
return MainDataSource.CreateNavigator();
}
}
Call from your method:
ClearListBox("/my"myFields/my:listLocations/my:listLocationsItem", Root);
Here is the ClearListBox method:
public void ClearListBox(string xp_ListBox, XPathNavigator xNav)
{
//clear list box of items
XPathNodeIterator lstClear = xNav.Select(xp_ListBox, NamespaceManager);
if (lstClear.Count > 0)
{
for (int i = lstClear.Count; i > 0; i--)
{
XPathNavigator reList = MainDataSource.CreateNavigator();
XPathNavigator reListItems = reList.SelectSingleNode(xp_ListBox + "[" + i + "]", NamespaceManager);
reListItems.DeleteSelf();
}
}
}
I am using a Property for Root:
private XPathNavigator Root
{
get
{
return MainDataSource.CreateNavigator();
}
}