Bryan Reynolds

Software, Business, Life . . .

About the author

Author Name is someone.
E-mail me Send mail

Recent posts

Recent comments

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008

C# Wrapping text using split and List<>

Below is a useful snippet of code to wrap text into a list of strings.

 

Example

"The quick brown fox jumps over the lazy dog"

 

Lets say you need to fit this into a multi-line text box with a width or around 12 characters and an unlimited height.

 

The function will return a list of strings without splitting the individual words.

 

   1: var result = Wrap("The quick brown fox jumps over the lazy dog", 12);

 

result [0] = "The quick"

result [1] = "brown fox "

result [2] = "jumps over"

result [3] = "the lazy dog"

 

This function was used for reporting writing and formatting logs.

 

The function takes a string of any size and returns a list of string no larger than the max length input variable.

 

Let me know if this was useful.

   1: using System;
   2: using System.Collections.Generic;
   3:  
   4: /// <summary>
   5: /// Summary description for StringExtention
   6: /// </summary>
   7: public class StringExtention
   8: {
   9:     /// <summary>
  10:     /// Returns a list of strings no larger than the max length sent in.
  11:     /// </summary>
  12:     /// <remarks>useful function used to wrap string text for reporting.</remarks>
  13:     /// <param name="text">Text to be wrapped into of List of Strings</param>
  14:     /// <param name="maxLength">Max length you want each line to be.</param>
  15:     /// <returns>List of Strings</returns>
  16:     public static List<String> Wrap(string text, int maxLength)
  17:     {
  18:  
  19:         // Return empty list of strings if the text was empty
  20:         if (text.Length == 0) return new List<string>();
  21:  
  22:         var words = text.Split(' ');
  23:         var lines = new List<string>();
  24:         var currentLine = "";
  25:  
  26:         foreach (var currentWord in words)
  27:         {
  28:  
  29:             if ((currentLine.Length > maxLength) ||
  30:                 ((currentLine.Length + currentWord.Length) > maxLength))
  31:             {
  32:                 lines.Add(currentLine);
  33:                 currentLine = "";
  34:             }
  35:  
  36:             if (currentLine.Length > 0)
  37:                 currentLine += " " + currentWord;
  38:             else
  39:                 currentLine += currentWord;
  40:  
  41:         }
  42:  
  43:         if (currentLine.Length > 0)
  44:             lines.Add(currentLine);
  45:  
  46:         
  47:         return lines;
  48:     }
  49:  
  50:  
  51: }
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: C#
Posted by Bryan on Wednesday, May 07, 2008 11:04 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Using LINQ to SQL instead of a sub report.

The post described how to use "Linq to SQL" with XtraReports and DevExpress for displaying relational data within a column of a report.

 

As a developer's we have all made many reports and used many tools to generate reports. Currently I am working with DevExpress's XtraReports Suite and "LINQ to SQL".  For web based relational database system reporting there tools are pretty easy to work with. 

 

Below is a sample output from a report that I am working on.  The interesting challenge was the 1 to many relationship within the Competitor column.

 

  XtraReport1

 

The competitor column needs to report all competitors from a 1 to many relationship table. There are many possible solutions to this common problem.  Using XtraReports you can make a subreport, you could set the text of the control by pulling the data from the database, or you could have a stored procedure format that data in the SQL engine you use prior to printing the report.

 

I chose to use "LINQ to SQL" for its quick implementation and ease of use.  If you have not had a chance to look at this technology take a look at Scott Gu's post.

 

In shorts order I was able to have a strongly type set of code that loaded a string with the exact format I needed to solve the problem.

   1: private void Detail_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e)
   2:    {
   3:        var projectID = Convert.ToInt32(GetCurrentColumnValue("ProjectID"));
   4:        var db = new dbDataContext();
   5:  
   6:        var queryCompitetion = from recs in db.ProjectCompetitions
   7:                               join comprecs in db.Competitions on recs.CompetitionID equals comprecs.CompetitionID
   8:                               where recs.ProjectID == projectID
   9:                               select new
  10:                                          {
  11:                                              recs.Distance,
  12:                                              recs.Direction,
  13:                                              comprecs.Name,
  14:  
  15:                                          };
  16:  
  17:        var stringBuiler = new StringBuilder();
  18:  
  19:        for (int i = 0; i < queryCompitetion.ToList().Count-1; i++)
  20:        {
  21:            var recs = queryCompitetion.ToList()[i];
  22:            stringBuiler.AppendFormat("{0}/ {1}{2}    ", recs.Name, recs.Distance, recs.Direction);
  23:  
  24:            if ((i + 1) % 2 == 0) stringBuiler.Append("\r\n");
  25:        }
  26:  
  27:        
  28:        xrCompetitorCell.Text = stringBuiler.ToString();
  29:    }

 

The "Detail_BeforePrint" function fires off before each report detail line is displayed.   Using the GetCurrentColumnValue function I retrieved the ProjectID for the current line.  Used "Linq to SQL" to grab the appropriate data using strong typing.  Iterated through the result and add the formatted string to the "xrCompetitorCell".  The "xrCompetitorCell" is a property of the report and generated via DevExpress's designer.

 

Hope this was useful from you.

 

Bryan

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by Bryan on Wednesday, April 30, 2008 7:21 AM
Permalink | Comments (0) | Post RSSRSS comment feed

LLBLGen Pro and Microsoft’s Dynamic Data will play nice!

I am a big fan of LLBLGen Pro, an n-tier generator and O/R mapper, written mostly by Frans Bouma.  For those of you who are not familiar with this product the true value is its creator and evangelist Frans Bouma.  The quality product, support and enthusiasm brought by him and his organization is refreshing.

Also recently Microsoft has been working on a ASP.NET extension called Dynamic Data.  Dynamic Data currently was scheduled to work with Microsoft O/R mapping initiatives LINQ to SQL and the Entity Framework.  Dynamic Data is designed to allow developers to quickly create CRUD pages surrounded by a base scaffolding with a central place to update UI and Validation logic.  I know that was a mouthful, and if you are looking for more information there are numerous blogs and sites that you can look at to get familiar with this technology. Some of the more prominent links are below.

Good news!

Both Dynamic Data and LLBLgen will be playing nice.  It started about a month ago when I was talking David Ebbo whether or not the extension was going to work with other O/R tools and with Frans Bouma about Dynamic Data.  After I took Frans through a demo he immediately contacted Microsoft to make it happen.  Today I got the email from him telling me they were going to release the product with the appropriate API to allow his product to integrate with Dynamic Data.

I will hopefully have time to go through the bits Frans sent me today.  I am excited this produced a situation where I get what I believe to be the best of both worlds, for small projects.

Microsoft was not planning on releasing this API until this happened and I applaud both Microsoft and Frans for bringing the tools together for the community to enjoy.

Thanks!

Bryan Reynolds

C# Developer

Untitled

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by Bryan on Friday, April 25, 2008 3:29 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Interesting article about the new C# "var"

Ilya Ryzhenkov, a .NET Tools Product Manager at JetBrains, relays some of his thoughts on the var keyword here.

If you had a chance to use some of the latest c# language features you have no doubt heard of var.  Coming from the idea of KISS, keep it simple stupid, I not only agree with Ilya, but would say that this is the way it should have always been.  Especially now that we are in the day of IDE's and IDE addon's like JetBrain's resharper we should be reducing the amount of code we need to maintain and making the syntax easier to read.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: C#
Posted by Bryan on Wednesday, April 23, 2008 11:58 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Dynamic Data - New Code Drop

If you have not had a chance to check out Microsoft's DynamicData you should.  I have been working on the latest bits via Microsoft Connect and I have been pleased.  It does not fit every need of course.  Its not "Enterprise Level" and we can debate what that means for ever.  Suffice it to say,  if you have a large complex architecture with many developers,  this is not the tool.  Good news is not all projects are like that.  For the many small applications that offices and companies of all size need on a regular basis.  This will fill the bill. 

Below with virtually no code I was able to modify the default templates to make a customer detail screen that shows the customers jobs.  The field captions all the way to the validation are described in a single location to reduce the amount of work you have to do.  Its all about being lazy!  Or better yet code reduction without functionality reduction.

You can see links on the left below that shows a list of links to function of this tiny program.  After talking with the client for about 3 hours.  I generated in 30 minutes a complete site for data entry.  As the customer requested changes I was able to quickly respond to there requests. 

DynamicData1 

If a field is required via a not null property on your data field via SQL Server.  Then the data validation on the screen is linked as well.

New Picture

Conclusion

Looks like Microsoft is listening to there customers.  As a software developer you must take a look at this tool.

Bryan MCPD

C# Developer

Untitled

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: ASP.NET | Dynamic Data
Posted by Bryan on Thursday, April 10, 2008 8:34 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Fraudulent Companies

Yesterday I got a frantic call from one of our clients. They were concerned that one of the marketing campaigns we manage through our lead system was not performing. They mentioned after looking at some reports they were concerned that this campaign had shut down. Leads were being submitted perfectly fine one day then not at all the next. They thought the system was broken. It was a valid question. I investigated.

During the conversation I looked at the reports myself and quickly realized that someone was messing with us. They were submitting leads at an almost 1 for 1 basis to visits. This was not the pattern we saw for any other lead campaign. 50 visits to a lead was more realistic. This campaign was not only performing at an almost 1 to 1 basis, but all leads were valid on entry. This is of course not realistic either. Normally we see a 5 to 1 ratio on a user submitting a lead and it passing all the validation checks to make sure it’s a real lead. This is not standard for everyone, I am sure. Depending on the validation logic your system has the numbers can be very different. Either way, this was a problem.

We are dealing with this now by adding preventative logic to the system.

Why do they do it? What can be done with people like this?

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by Bryan on Tuesday, March 18, 2008 7:25 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Mocking using TypeMock

Unit testing and using the mocking pattern are new to my team and I.  After talking with Ron Shoshani at TypeMock they decided put a video up for beginners.


This video shows you how to break constructor dependency when writing unit tests.  Constructor dependency is when you one object depends on another during the creation or construction.  When another object is used in the constructor it binds the classes together in a way that makes testing discrete concerns more difficult.

To solve this problem without TypeMock developers would use the Mock Object Pattern.  Usually through the use of interfaces a class is created for the use in the test that mocks or mimics what the real functionality would be.  Usually this is a simple implementation that does not actually perform the true work that would be needed to implement the interface.  The implementation would be just enough to complete the unit tests that use it. This new implementation would then be used in the unit test of the class you wanted to test.


With TypeMock you will be able to mock objects that do not have interfaces, and even more powerful you don't even have to create the mock object implementation.  This makes testing objects that have dependant objects much easier to test.


If you have not checked out TypeMock you should do so.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Agile
Posted by Bryan on Wednesday, January 30, 2008 5:04 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Datatable Pivot/Crosstab

Using Visual Studio Team System 2008 internal unit testing environment I create the code and the unit test for my pivot table class. Having written this code before without unit testing.  I rewrote this with agile development in mind.  Basically this code takes a datatable that you want to transform.  A key column that defines each unique row.  A variable column that will display across the top and a value column representing the data for it.

For this example to work you need to sort the table by that key column.  Alternatively, I could add some code to make sure that happens in the view.  Will probably update that later.

For those of you that are new to unit testing this was a perfect example of a time when testing came in handy.  When I tested the code without variable columns that where of type date the class worked great.  As soon as I change the data to a date field the unit test crashed.  Below is the result of the modified code by adding ".tostring"

Code for the PivotTable Class

Namespace GEN.DL.Transformation
 
    Public Class PivotTable
 
        Private lSourceTable As DataTable
        Private lVariableColumn As DataColumn
        Private lAggregateColumn As DataColumn
        Private lKeyColumn As DataColumn
        Private lDestinationTable As New DataTable
 
 
#Region "Public Properties"
 
        ''' <summary>
        ''' Pivot datatable
        ''' </summary>
        Public Sub New(ByVal mSourceTable As DataTable, ByVal mKeyColumn As DataColumn, _
                       ByVal mVariableColumn As DataColumn, ByVal mValueColumn As DataColumn)
 
            lSourceTable = mSourceTable
            lKeyColumn = mKeyColumn
            lVariableColumn = mVariableColumn
            lAggregateColumn = mValueColumn
 
        End Sub
 
#End Region
 
        ''' <summary>
        ''' Pivots a datatable
        ''' </summary>
        ''' <returns>Returns pivot datatable</returns>
        Public Function Transform() As DataTable
 
            Dim mColumn As DataColumn ' Column used in for each to add non essential columns
            Dim mSourceDataRow As DataRow ' Source Row
            Dim mDestinationDataRow As DataRow = Nothing ' Row to be Added
            Dim mCurrentKeyValue As String = "" ' Current Key Name
            Dim mCurrentColumn As String = "" ' Current Column Name
 
 
            ' Add All the columns excluding the aggregate and the Variable Column
            For Each mColumn In lSourceTable.Columns
 
                If mColumn.Ordinal <> lVariableColumn.Ordinal AndAlso _
                   mColumn.Ordinal <> lAggregateColumn.Ordinal Then
 
                    lDestinationTable.Columns.Add(mColumn.ColumnName, mColumn.DataType)
 
                End If
            Next
 
            For Each mSourceDataRow In lSourceTable.Rows ' Main Process to add values to pivot table
 
                ' Set the current Column Value
                mCurrentColumn = mSourceDataRow(lVariableColumn.Ordinal).ToString
 
                If Not lDestinationTable.Columns.Contains(mCurrentColumn) Then ' Column is new
 
                    Dim lDataColumn As DataColumn = lDestinationTable.Columns.Add(mCurrentColumn, lAggregateColumn.DataType)
 
                    ' set the index so that it is sorted properly:
                    Dim newOrdinal As Integer = lDataColumn.Ordinal
                    Dim i As Integer
 
                    For i = newOrdinal - 1 To lSourceTable.Columns.Count - 2 Step -1
                        If lDataColumn.ColumnName.CompareTo(lDestinationTable.Columns(i).ColumnName) < 0 Then
                            newOrdinal = i
                        End If
                    Next
                    lDataColumn.SetOrdinal(newOrdinal)
 
                End If
 
                If mCurrentKeyValue <> mSourceDataRow(lKeyColumn.Ordinal).ToString Then ' New Row
 
                    If Not mCurrentKeyValue = "" Then ' First row
                        lDestinationTable.Rows.Add(mDestinationDataRow)
                    End If
 
                    mCurrentKeyValue = mSourceDataRow(lKeyColumn.Ordinal).ToString
                    mDestinationDataRow = lDestinationTable.NewRow()
 
                    For Each mColumn In lSourceTable.Columns
 
                        If mColumn.Ordinal <> lVariableColumn.Ordinal AndAlso _
                           mColumn.Ordinal <> lAggregateColumn.Ordinal Then
 
                            mDestinationDataRow(mColumn.ColumnName) = mSourceDataRow(mColumn.ColumnName)
 
                        End If
                    Next
 
                End If
 
                mDestinationDataRow(mCurrentColumn) = mSourceDataRow(lAggregateColumn.Ordinal)
 
            Next
 
            ' If rows where added, add the last row
            If mCurrentKeyValue.Length > 0 Then lDestinationTable.Rows.Add(mDestinationDataRow)
 
            Return lDestinationTable
 
        End Function
 
    End Class
 
End Namespace

 

Code for the unit tests.

Imports System.Data
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports GEN.DL.Transformation

'''<summary>
'''This is a test class for PivotTableTest and is intended
'''to contain all PivotTableTest Unit Tests
'''</summary>
<TestClass()> _
Public Class PivotTableTest


    Private testContextInstance As TestContext

    '''<summary>
    '''Gets or sets the test context which provides
    '''information about and functionality for the current test run.
    '''</summary>
    Public Property TestContext() As TestContext
        Get
            Return testContextInstance
        End Get
        Set(ByVal value As TestContext)
            testContextInstance = value
        End Set
    End Property

    '''<summary>
    '''A test for Transform
    '''</summary>
    <TestMethod()> _
    Public Sub TransformTestGeneral()

        Dim mSourceTable As New DataTable("TestPivotTable")
        Dim mKeyColumn As New DataColumn("Key", System.Type.GetType("System.DateTime"))
        Dim mVariableColumn As New DataColumn("Variable", System.Type.GetType("System.DateTime"))
        Dim mAggregateColumn As New DataColumn("Aggregate", System.Type.GetType("System.Int32"))
        Dim mDataRow As DataRow

        mSourceTable.Columns.Add(mKeyColumn)
        mSourceTable.Columns.Add(mVariableColumn)
        mSourceTable.Columns.Add(mAggregateColumn)

        ' Row #1
        mDataRow = mSourceTable.NewRow
        mDataRow("Key") = "1/1/2008"
        mDataRow("Variable") = "1/1/2008"
        mDataRow("Aggregate") = 1
        mSourceTable.Rows.Add(mDataRow)

        mDataRow = mSourceTable.NewRow
        mDataRow("Key") = "1/1/2008"
        mDataRow("Variable") = "1/2/2008"
        mDataRow("Aggregate") = 2
        mSourceTable.Rows.Add(mDataRow)

        mDataRow = mSourceTable.NewRow
        mDataRow("Key") = "1/1/2008"
        mDataRow("Variable") = "1/3/2008"
        mDataRow("Aggregate") = 3
        mSourceTable.Rows.Add(mDataRow)

        ' Row #2
        mDataRow = mSourceTable.NewRow
        mDataRow("Key") = "1/2/2008"
        mDataRow("Variable") = "1/1/2008"
        mDataRow("Aggregate") = 1
        mSourceTable.Rows.Add(mDataRow)

        mDataRow = mSourceTable.NewRow
        mDataRow("Key") = "1/2/2008"
        mDataRow("Variable") = "1/2/2008"
        mDataRow("Aggregate") = 2
        mSourceTable.Rows.Add(mDataRow)

        mDataRow = mSourceTable.NewRow
        mDataRow("Key") = "1/2/2008"
        mDataRow("Variable") = "1/3/2008"
        mDataRow("Aggregate") = 3
        mSourceTable.Rows.Add(mDataRow)

        ' Row #3
        mDataRow = mSourceTable.NewRow
        mDataRow("Key") = "1/3/2008"
        mDataRow("Variable") = "1/1/2008"
        mDataRow("Aggregate") = 1
        mSourceTable.Rows.Add(mDataRow)

        mDataRow = mSourceTable.NewRow
        mDataRow("Key") = "1/3/2008"
        mDataRow("Variable") = "1/2/2008"
        mDataRow("Aggregate") = 2
        mSourceTable.Rows.Add(mDataRow)

        mDataRow = mSourceTable.NewRow
        mDataRow("Key") = "1/3/2008"
        mDataRow("Variable") = "1/3/2008"
        mDataRow("Aggregate") = 3
        mSourceTable.Rows.Add(mDataRow)


        Dim target As PivotTable = New PivotTable(mSourceTable, mKeyColumn, mVariableColumn, mAggregateColumn)

        Dim actual As DataTable
        actual = target.Transform

        Assert.AreEqual(3, actual.Rows.Count, "Should have 3 rows")
        Assert.AreEqual(4, actual.Columns.Count, "Should have 4 columns")
        Assert.AreEqual(2, actual.Rows(1)(2), "Value in Column 1 2 should be ""2""")

        'Assert.Inconclusive("Verify the correctness of this test method.")

    End Sub


    '''<summary>
    ''' Test to see when a column is added that the correct ordinal is set.
    ''' If Column 2 is added before 3 does it show as 2 or 3.
    ''' Correct outcome should be 1,2,3
    '''</summary>
    <TestMethod()> _
    Public Sub TransformTestColumnAddingOrder()
        Dim mSourceTable As New DataTable("TestPivotTable")
        Dim mKeyColumn As New DataColumn("Key", System.Type.GetType("System.DateTime"))
        Dim mVariableColumn As New DataColumn("Variable", System.Type.GetType("System.String"))
        Dim mAggregateColumn As New DataColumn("Aggregate", System.Type.GetType("System.Int32"))
        Dim mDataRow As DataRow

        mSourceTable.Columns.Add(mKeyColumn)
        mSourceTable.Columns.Add(mVariableColumn)
        mSourceTable.Columns.Add(mAggregateColumn)

        ' Row #1
        mDataRow = mSourceTable.NewRow
        mDataRow("Key") = "1/1/2008"
        mDataRow("Variable") = "Column1"
        mDataRow("Aggregate") = 1
        mSourceTable.Rows.Add(mDataRow)

        ' Row #2
        mDataRow = mSourceTable.NewRow
        mDataRow("Key") = "1/2/2008"
        mDataRow("Variable") = "Column1"
        mDataRow("Aggregate") = 1
        mSourceTable.Rows.Add(mDataRow)

        mDataRow = mSourceTable.NewRow
        mDataRow("Key") = "1/2/2008"
        mDataRow("Variable") = "Column3"
        mDataRow(