warrenrapson – the blog

scripts and thoughts from my work and hobby

SSRS Query for Report Executions

Posted by warrenrapson on August 19, 2010

I whipped up this query to put in a report to give me a list of the executions of our SQL Server Reporting Services reports and their run counts with the user and additional details being available on a drill down. It’s a simple query and very easy to adapt.

SELECT C.[Path], C.CreationDate, CU.UserName as CreatedBy, C.ModifiedDate, MU.Username as ModifiedBy,  E.Username as RunBy, E.TimeStart as DateTimeRun, DATEDIFF("ss", E.TimeStart, E.TimeEnd) as ExecutionTime, E.Parameters as RunParameters

FROM [Catalog] C
 LEFT JOIN Users CU ON C.CreatedById = CU.UserID
 LEFT JOIN Users MU ON C.ModifiedById = MU.UserID
 LEFT JOIN ExecutionLog E ON C.ItemID = E.ReportID
WHERE C.[Type] = 2 -- reports only
ORDER BY C.[Path], RunBy, E.TimeStart

Posted in SQL | Leave a Comment »

Get values from an SQL Stored Procedure into Excel (VBA macro)

Posted by warrenrapson on May 25, 2010

I’m using the below function in an Excel macro to get the results of a simple stored procedure into an Excel spreadsheet. The function needs the connection string defined within it, but this can easily setup to be dynamic in the function parameters if needed. Also I’m only using one parameter, but I have no doubt that you create a multi-value function parameter to take several stored proc parameters.

In your macro, simply call the function and it will populate cells with your stored proc results beginning at the current active cell.

Function insertStoredProcValues(spName As String, strParameter As String)

    Dim Conn As ADODB.Connection
    Dim ADODBCmd As ADODB.Command
    Dim rs As ADODB.Recordset
    Dim i As Integer
    Dim sConnect As String

    '--DEFINE CONNECTION STRING HERE---------------------------------------------------------
    sConnect = "driver={sql server}; server=MYSERVERNAME; Database=MYDATABASENAME; UID=MYUSERNAME; PWD=MYPASSWORD;"
    '----------------------------------------------------------------------------------------

    'Establish connection
    Set Conn = New ADODB.Connection
    Conn.ConnectionString = sConnect
    Conn.Open

    'Open recordset
    Set ADODBCmd = New ADODB.Command
    ADODBCmd.ActiveConnection = Conn
    ADODBCmd.CommandText = spName
    ADODBCmd.CommandType = adCmdStoredProc
    ADODBCmd.Parameters.Refresh
    ADODBCmd.Parameters(1).Value = strParameter
    Set rs = ADODBCmd.Execute()

    'Loop through recordset and place values
    rs.MoveFirst
    Do While rs.EOF = False
        For i = 0 To rs.Fields.Count - 1
            ActiveCell.Value = rs.Fields(i).Value   'insert value into cell
            ActiveCell.Offset(0, 1).Activate        'move to next cell for next value
        Next i
        ActiveCell.Offset(1, -i).Activate           'move to next row for next record
    rs.MoveNext
    Loop

    'Clean up
    rs.Close
    Set rs = Nothing
End Function
 

Posted in Excel, SQL, VBA | Leave a Comment »

SSIS: Output SQL to XML file

Posted by warrenrapson on November 23, 2009

I wanted to create an XML file from an SQL table using SSIS. I found the following blog, but the method I used is in the user comments from “J. Morgan Smith”. I also had to do what “sam” and “BB88″ said.

http://consultingblogs.emc.com/jamiethomson/archive/2006/07/11/4209.aspx

 

Posted in SQL | Tagged: , | Leave a Comment »

SQL Reporting Services Date Parameters

Posted by warrenrapson on November 12, 2009

Again, I’m posting these here mainly to assist in my own forgetfulness.

Start of Month: =DateAdd("d", -datepart("d", Today()) +1, Today())

Start of Last Month: =DateAdd("m", -1, DateAdd("d", -datepart("d", Today()) +1, Today()))

Last Day of Last Month: =DateAdd("d", -datepart("d", Today()) , Today())

Posted in SQL | Tagged: , | Leave a Comment »

Having trouble bridging your modem and your Astaro Security Gateway?

Posted by warrenrapson on July 28, 2009

I know I was. I just couldn’t get the thing to connect when I change my ASG’s external interface from ‘Cable Modem (DHCP)’ to PPPoE.

The answer? Instead of changing the interface delete it first and just re-create it – worked a charm for me!

Also worth noting that deleting the interface took my NAT settings with it – I just reverted to the backup, took some screen shots and then recreated them.

Posted in Networking | Tagged: , | Leave a Comment »

MS Access – Link tables with VBA

Posted by warrenrapson on July 7, 2009

Just posting this here because I can never remember it myself. I can also never find it online either so it might be simple and handy to others too…

Sub LinkTables()
    Dim tbl As New TableDef
    Dim ConnectString As String

    ConnectString = "ODBC;DRIVER=SQL Server;SERVER=myServerName;DATABASE=myDatabaseName;uid=myUserID;pwd=myPa$$w0rd"

    Set tbl = New TableDef
    On Error Resume Next

    tbl.Name = "destinationTableName"
    tbl.SourceTableName = "sourceTableName"
    tbl.Connect = ConnectString
    CurrentDb.TableDefs.Append tbl
End Sub

Posted in VBA | Tagged: , | 1 Comment »

Google mail as a backup email server/mail queue using Small Business Server 2008

Posted by warrenrapson on June 22, 2009

This is an expansion of an idea I saw here http://weblogs.asp.net/guybarrette/archive/2008/05/25/using-gmail-as-a-backup-mail-server.aspx

The situation:

I have a small business with one server running SBS 2008 and I want email redundancy so that I don’t miss any email while my server is down for maintenance, power failure, etc. I also don’t want the hassle of periodically checking my off-site email address to see if anything has end up there, hence, I want a mail queue.

The solution:

  • Sign up for Google Apps email account (www.google.com/a).
  • Replicate your user accounts on the Google mail. You may as well use the one administrator password for all accounts because users will never need to log in themselves.
  • Assign your secondary MX records to point to the Google addresses specified in the settings they give.

At this point, Google will receive your mail if your server is unreachable.

  • On the SBS Console, click the Netwtorking tab, then the Connectivity tab
  • Setup the SBS POP 3 Connector using the information available in the Google settings for each account
  • Setup the POP/Forwarding in each Google account and you’re done!

So now, if your server is unreachable, Google will get your mail. When your server is back up, it will query the Google inboxes at the intervals you specified and forward your mail to where it needs to go!

Posted in General | 1 Comment »

SharePoint Event Handler to set Item-Level Security based on Names in a List Column

Posted by warrenrapson on May 20, 2009

First, I would like to credit a lady by the name of Mirjam for her piece at http://www.sharepointblogs.com/mirjam/archive/2007/11/11/setting-item-level-security-in-an-eventhandler.aspx; it was the starting point that I so desperately needed to build this – thanks Mirjam!

What I have here is piece of code that takes the information of two columns, ‘WriteSecurity’ and ‘ReadSecurity’ and sets Contribute and Read permissions respectively on a document library item. This allows the user to choose security for the document that they create/upload at the time of their create/upload.

It is a feature that overrides the ItemUpdating and ItemUpdated events in a site collection. The feature first looks for the columns, WriteSecurity and ReadSecurity; if it does not find both of them, it ignores the rest of the process and continues as normal. If it does find them both, it will check for data within those columns; if no data is present, the method will have the item inherit permissions from its containing library. If it finds that only the ReadSecurity column is filled, it will throw an error saying that Read without Write permissions are not allowed. Otherwise the process will cycle through the users/groups specified and assign the appropriate permissions. All of this is done with elevated permissions, but the ‘Modified By’ column will be that of the calling user.

I’ve spent a lot of time on this code, but I was not a C# programmer when I started and I knew nothing of SharePoint event receivers and code-based modification. That said, this has worked in two environments. I would imagine, however, that an experienced programmer/SharePoint Guru, would identify my messy bits and suggest better approaches (please do!) especially with my method of extracting user IDs from the security columns, and the way I repeat the code for the Write and Read bits.

This has been designed to work with Document Libraries. As said before, the feature looks for the columns ‘WriteSecurity’ and ‘ReadSecurity’ with no spaces – at least, the columns in the library should be created that way; you can rename after. And I believe that this may not work if your user’s domain starts with a number…

For those who are like I was when I first created this, he’s the summarised approach to take:

  1. Using Visual Studio, create a C# Class Library Project
  2. Add a reference to Windows SharePoint Services
  3. Rename the class to SetPermissionsEventhandler
  4. Copy the C# code into the project
  5. Sign the project with a strong key
  6. Build it
  7. Drag the resulting DLL from the project’s bin folder into the c:\windows\assembly folder on the SharePoint server.
  8. Copy the Public Key Token from the DLL now in the assembly
  9. Go to C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\ on the SharePoint server
  10. Create a folder called SetPermissionsEventhandler
  11. Within that, create two files, Feature.xml and Elements.xml
  12. Copy the respective XML codes (specified below) into the files
  13. Open a command prompt
  14. Go to C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN
  15. Run this: stsadm -o installfeature -filename SetPermissionsEventhandler\Feature.xml
  16. Run this: stsadm -o activatefeature -filename SetPermissionsEventhandler\Feature.xml -url http://YOURSITECOLLECTION
  17. Run this: iisreset
  18. If you haven’t already, create a Document Library with ‘People or Group’ columns called ‘WriteSecurity’ and ‘ReadSecurity’
  19. Enjoy.

Class Code:

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using System.Security;
using System.Security.Principal;
using System.Security.Permissions;
using System.Text.RegularExpressions;

namespace SetPermissionsEventhandler
{
    public class SetPermissions : SPItemEventReceiver
    {
        public override void ItemUpdating(SPItemEventProperties properties)
        {
            base.ItemUpdating(properties);
            //make sure security fields exist
            if (properties.ListItem.Fields.ContainsField("WriteSecurity") == true &&
                properties.ListItem.Fields.ContainsField("ReadSecurity") == true)
            {
                // check to see if the user has set Read Security without setting
                // Write Security. If so, show error page and cancel the process.
                if (properties.AfterProperties["WriteSecurity"].ToString() == ""
                    && properties.AfterProperties["ReadSecurity"].ToString() != "")
                {
                    properties.Cancel = true;
                    properties.ErrorMessage = "You cannot specify Read Security without also specifying Write Security. " +
                        "\r\n\r\nPlease click your browser's BACK button to try again.";
                }
            }
        }
       
       
        //this will fire if the ItemUpdating event was not cancelled
        public override void ItemUpdated(SPItemEventProperties properties)
        {
            //make sure security fields exist again
            if (properties.ListItem.Fields.ContainsField("WriteSecurity") == true &&
                properties.ListItem.Fields.ContainsField("ReadSecurity") == true)
            {
                //make sure that file is not checked-out before setting any permissions
                if (properties.ListItem.File.CheckOutStatus == SPFile.SPCheckOutStatus.None)
                {
                    //if no security data has been specified, inherit the permission of the
                    //containing library otherwise run the method to set the permissions
                    if (properties.AfterProperties["WriteSecurity"].ToString() == ""
                        && properties.AfterProperties["ReadSecurity"].ToString() == "")
                    {
                        InheritLibraryPermission(properties);
                    }
                    else
                    {
                        SetNewPermissions(properties);
                    }
                }
            }
        }
 
        private void InheritLibraryPermission(SPItemEventProperties properties)
        {
            Guid siteID,webID,listID;
            int itemID;
            listID = properties.ListId;
            itemID = properties.ListItem.ID;
            using (SPWeb web = properties.OpenWeb())
            {
                siteID = web.Site.ID;
                webID = web.ID;
            }
            //get the calling user id for later use
            String callingUserID = properties.CurrentUserId.ToString();
            //run this block as System Account
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(siteID))
                {
                    using (SPWeb web = site.OpenWeb(webID))
                    {
                        SPList list = web.Lists[listID];
                        SPRoleAssignmentCollection roles = list.RoleAssignments;
                        SPListItem updatedItem = list.GetItemById(itemID);
                        updatedItem.ResetRoleInheritance();
                        this.DisableEventFiring();
                        //sets the 'Modified By' column as the calling user, not the System Account
                        updatedItem["Editor"] = callingUserID;
                        updatedItem.Update();
                        this.EnableEventFiring();
                    }
                }
            });
        }
 

        private void SetNewPermissions(SPItemEventProperties properties)
        {
            Guid siteID,webID,listID;
            int itemID;
            listID = properties.ListId;
            itemID = properties.ListItem.ID;
            //get the calling userid for later use
            String callingUserID = properties.CurrentUserId.ToString();
            using (SPWeb web = properties.OpenWeb())
            {
                siteID = web.Site.ID;
                webID = web.ID;
            }
            //run this block as System Account
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(siteID))
                {
                    using (SPWeb web = site.OpenWeb(webID))
                    {
                        SPList list = web.Lists[listID];
                        SPRoleAssignmentCollection roles = list.RoleAssignments;
                        SPListItem updatedItem = list.GetItemById(itemID);
                        updatedItem.BreakRoleInheritance(false);
                        SPRoleDefinitionCollection roleDefinitions = web.RoleDefinitions;
                        SPRoleAssignmentCollection roleAssignments = updatedItem.RoleAssignments;
                        SPUserCollection users = web.AllUsers;
                        //SPGroupCollection groups = web.Groups;
                        SPGroupCollection groups = web.SiteGroups;
                        //Remove all Permissions before applying chosen permissions
                        for (int x = updatedItem.RoleAssignments.Count - 1; x >= 0; --x)
                        {
                            updatedItem.RoleAssignments.Remove(x);
                        }
                        //set write permissions
                        foreach (String eachUserID in getUserIDsFromPeopleColumn(updatedItem.File.Properties["WriteSecurity"].ToString()))
                        {
                            int intID = Int32.Parse(eachUserID);
                            //determine if ID is user or group
                            Boolean isGroup = false;
                            foreach (SPGroup testGroup in web.SiteGroups)
                            {
                                if (testGroup.ID == intID)
                                {
                                    isGroup = true;
                                }
                            }
                            if (isGroup == false) //user
                            {
                                SPUser userToAdd = users.GetByID(intID);
                                SPRoleAssignment roleAssignment = new SPRoleAssignment(userToAdd);
                                SPRoleDefinitionBindingCollection roleDefBindings = roleAssignment.RoleDefinitionBindings;
                                roleDefBindings.Add(roleDefinitions["Contribute"]);
                                roleAssignments.Add(roleAssignment);
                            }
                            else //group
                            {
                                SPGroup groupToAdd = groups.GetByID(intID);
                                SPRoleAssignment groupRoleAssignment = new SPRoleAssignment(groupToAdd);
                                SPRoleDefinitionBindingCollection groupRoleDefBindings = groupRoleAssignment.RoleDefinitionBindings;
                                groupRoleDefBindings.Add(roleDefinitions["Contribute"]);
                                roleAssignments.Add(groupRoleAssignment);
                            }
                        }

                        //repeat the above for Read permissions, if specifed
                        if (updatedItem.File.Properties["ReadSecurity"].ToString() != "")
                        {
                            //set permissions
                            foreach (String eachUserID in getUserIDsFromPeopleColumn(updatedItem.File.Properties["ReadSecurity"].ToString()))
                            {
                                int intID = Int32.Parse(eachUserID);
                                //determine if ID is user or group
                                Boolean isGroup = false;
                                foreach (SPGroup testGroup in web.SiteGroups)
                                {
                                    if (testGroup.ID == intID)
                                    {
                                        isGroup = true;
                                    }
                                }
                                if (isGroup == false) //user
                                {
                                    SPUser userToAdd = users.GetByID(intID);
                                    SPRoleAssignment roleAssignment = new SPRoleAssignment(userToAdd);
                                    SPRoleDefinitionBindingCollection roleDefBindings = roleAssignment.RoleDefinitionBindings;
                                    roleDefBindings.Add(roleDefinitions["Read"]);
                                    roleAssignments.Add(roleAssignment);
                                }
                                else //group
                                {
                                    SPGroup groupToAdd = groups.GetByID(intID);
                                    SPRoleAssignment groupRoleAssignment = new SPRoleAssignment(groupToAdd);
                                    SPRoleDefinitionBindingCollection groupRoleDefBindings = groupRoleAssignment.RoleDefinitionBindings;
                                    groupRoleDefBindings.Add(roleDefinitions["Read"]);
                                    roleAssignments.Add(groupRoleAssignment);
                                }
                            }
                        }
                        //update the item preventing further events
                        this.DisableEventFiring();
                        updatedItem["Editor"] = callingUserID; //sets the 'Modified By' column as the calling user, not the System Account
                        updatedItem.Update();
                        this.EnableEventFiring();
                    }
                }
            });
        }
 
        public string[] getUserIDsFromPeopleColumn(String rawUsers)
        {
            rawUsers = "#" + rawUsers;
            string[] rawUsersArray = rawUsers.Split(';');
            string Users = "";
            foreach (string eachUser in rawUsersArray)
            {
                if (System.Text.RegularExpressions.Regex.IsMatch(eachUser.Substring(1, 1), "^[A-Za-z]$") == false)
                {
                    Users = Users + eachUser.Substring(1) + ";";
                }
            }
            Users = Users.Substring(0, Users.Length - 1);
            string[] UsersArray = Users.Split(';');
            return UsersArray;
        }
    }
}

 

 

 

Feature.xml

<Feature Scope="Web"
   Title="Set Permissions Event Handler"
   Description="This feature takes the People and Groups identified in the 'Write Security' and 'Read Security' columns in Document Libraries and applies the relevant permissions to each item when it is edited. If the item is checked-out, the permissions will not be applied until the item is checked back in. To enable this feature's functionality in a Document Library, 'Person or Group' columns must be created with the names, WriteSecurity and ReadSecurity (with no spaces); they can be renamed thereafter."
   Id="CREATEANEWGUIDANDPUTITHERE"
   xmlns="http://schemas.microsoft.com/sharepoint/">
   <ElementManifests>
      <ElementManifest Location="Elements.xml"/>
   </ElementManifests>
</Feature>

 

 

Elements.xml

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   <Receivers ListTemplateId="101">
      <Receiver>
         <Name>SetPermissionsEventhandler</Name>
         <Type>ItemUpdating</Type>
         <SequenceNumber>10000</SequenceNumber>
         <Assembly>SetPermissionsEventhandler, Version=1.0.0.0, Culture=neutral, PublicKeyToken=PUBLICKEYTOKENFROMYOURDLL</Assembly>
         <Class>SetPermissionsEventhandler.SetPermissions</Class>
         <Data></Data>
         <Filter></Filter>
      </Receiver>
      <Receiver>
         <Name>SetPermissionsEventhandler</Name>
         <Type>ItemUpdated</Type>
         <SequenceNumber>10000</SequenceNumber>
         <Assembly>SetPermissionsEventhandler, Version=1.0.0.0, Culture=neutral, PublicKeyToken=PUBLICKEYTOKENFROMYOURDLL</Assembly>
         <Class>SetPermissionsEventhandler.SetPermissions</Class>
         <Data></Data>
         <Filter></Filter>
      </Receiver>
   </Receivers>
</Elements>
 
 

Posted in SharePoint | Tagged: , | 10 Comments »

Word Macro to separate pages into separate documents

Posted by warrenrapson on March 31, 2009

This little piece of code takes a word document and saves each page as its own document with the filname “FILENAME_x”. I haven’t done extensive testing, but please feel free to comment.

    Dim i As Integer
    Dim varNumberPages As Variant
    varNumberPages = ActiveDocument.Content.Information(wdActiveEndAdjustedPageNumber)
    For i = 1 To varNumberPages
        Selection.GoTo What:=wdGoToPage, Which:=wdGoToNext, Count:=1, Name:=""
        Selection.Find.ClearFormatting
        With Selection.Find
            .Text = ""
            .Replacement.Text = ""
            .Forward = True
            .Wrap = wdFindContinue
            .Format = False
            .MatchCase = False
            .MatchWholeWord = False
            .MatchWildcards = False
            .MatchSoundsLike = False
            .MatchAllWordForms = False
        End With
        Selection.EndKey Unit:=wdStory, Extend:=wdExtend
        Selection.Cut
        Selection.TypeBackspace
        ActiveDocument.SaveAs FileName:="FILENAME_" & i & ".doc", FileFormat:= _
            wdFormatDocument, LockComments:=False, Password:="", AddToRecentFiles:= _
            True, WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:= _
            False, SaveNativePictureFormat:=False, SaveFormsData:=False, _
            SaveAsAOCELetter:=False
        Selection.WholeStory
        Selection.Delete Unit:=wdCharacter, Count:=1
        Selection.PasteAndFormat (wdPasteDefault)
        Selection.HomeKey Unit:=wdStory
    Next i

Posted in VBA | 1 Comment »

SharePoint folders showing as http locations and webfolders?

Posted by warrenrapson on March 25, 2009

Check that WebClient service is running on your local machine – it worked for me!

We had this problem in our Citrix and Terminal Server environments – for whatever reason, those servers had the WebClient service disabled. Without this serivce running we experienced odd errors in various pieces of software as they would not allow saving to a http location i.e. SharePoint.

Posted in General, SharePoint | 2 Comments »

 
Follow

Get every new post delivered to your Inbox.