Linq to Xlsx

by Brian Keating Mon, April 26 2010 23:02

A sample how to read a Excel 2007/2010 using Open XML SDK V2

(forgive the bad syntax highlighting)

 

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml.Packaging;

namespace ConsoleApplicationLinqToXlsx
{
    class Program
    {
        static void Main(string[] args)
        {
            //Declare variables to hold refernces to Excel objects.
            Workbook workBook;
            SharedStringTable sharedStrings;
            IEnumerable<Sheet> workSheets;
            WorksheetPart custSheet;
            WorksheetPart orderSheet;

            //Declare helper variables.
            string custID;
            string orderID;
            List<Customer> customers;
            List<Order> orders;

            //Open the Excel workbook.
            using (SpreadsheetDocument document =
              SpreadsheetDocument.Open(@"d:\Temp\ConsoleApplicationLinqToXlsx\TestOpenXMl.xlsx ", true))
            {
                //References to the workbook and Shared String Table.
                workBook = document.WorkbookPart.Workbook;
                workSheets = workBook.Descendants<Sheet>();
                sharedStrings =
                  document.WorkbookPart.SharedStringTablePart.SharedStringTable;

                //Reference to Excel Worksheet with Customer data.
                custID =
                  workSheets.First(s => s.Name == @"Customer").Id;
                custSheet =
                  (WorksheetPart)document.WorkbookPart.GetPartById(custID);

                //Load customer data to business object.
                customers =
                  Customer.LoadCustomers(custSheet.Worksheet, sharedStrings);

                //Reference to Excel worksheet with order data.
                orderID =
                  workSheets.First(sheet => sheet.Name == @"Order").Id;
                orderSheet =
                  (WorksheetPart)document.WorkbookPart.GetPartById(orderID);

                //Load order data to business object.
                orders =
                  Order.LoadOrders(orderSheet.Worksheet, sharedStrings);

                //List all customers to the console.
                //Write header information to the console.
                Console.WriteLine("All Customers");
                Console.WriteLine("{0, -15} {1, -15} {2, -5}",
                  "Customer", "City", "State");

                //LINQ Query for all customers.
                IEnumerable<Customer> allCustomers =
                    from customer in customers
                    select customer;

                //Execute query and write customer information to the console.
                foreach (Customer c in allCustomers)
                {
                    Console.WriteLine("{0, -15} {1, -15} {2, -5}",
                      c.Name, c.City, c.State);
                }
                Console.WriteLine();
                Console.WriteLine();


                //Write all orders over $100 to the console.
                //Write header information to the console.
                Console.WriteLine("All Orders over $100");
                Console.WriteLine("{0, -15} {1, -10} {2, 10} {3, -5}",
                  "Customer", "Date", "Amount", "Status");

                //LINQ Query for all orders over $100.
                //Join used to display customer information for the order.
                var highOrders =
                  from customer in customers
                  join order in orders on customer.Name equals order.Customer
                  where order.Amount > 100.00
                  select new
                  {
                      customer.Name,
                      order.Date,
                      order.Amount,
                      order.Status
                  };

                //Execute query and write information to the console.
                foreach (var result in highOrders)
                {
                    Console.WriteLine("{0, -15} {1, -10} {2, 10} {3, -5}",
                      result.Name, result.Date.ToShortDateString(),
                      result.Amount, result.Status);
                }
                Console.WriteLine();
                Console.WriteLine();


                //Report on customer orders by status.
                //Write header information to  the console.
                Console.WriteLine("Customer Orders by Status");

                //LINQ Query for summarizing customer order information by status.
                //There are two LINQ queries. 
                //Internal query is used to group orders together by status and
                //calculates the total order amount and number of orders.
                //External query is used to join Customer information.
                var sumoforders =
                  from customer in customers
                  select new
                  {
                      customer.Name,
                      statusTotals =
                          from order in orders
                          where order.Customer == customer.Name
                          group order.Amount by order.Status into statusGroup
                          select new
                          {
                              status = statusGroup.Key,
                              orderAmount = statusGroup.Sum(),
                              orderCount = statusGroup.Count()
                          }
                  };

                //Execute query and write information to the console.
                foreach (var customer in sumoforders)
                {
                    //Write Customer name to the console.
                    Console.WriteLine("-{0}-", customer.Name);
                    foreach (var x in customer.statusTotals)
                    {
                        Console.WriteLine("  {0, -10}: {2,2} orders totaling {1, 7}",
                          x.status, x.orderAmount, x.orderCount);
                    }
                    Console.WriteLine();
                }

                //Keep the console window open.
                Console.Read();
            }
        }

        /// <summary>
        /// Used to store customer information for analysis.
        /// </summary>
        public class Customer
        {
            //Properties.
            public string Name { get; set; }
            public string City { get; set; }
            public string State { get; set; }

            /// <summary>
            /// Helper method for creating a list of customers
            /// from an Excel worksheet.
            /// </summary>
            public static List<Customer> LoadCustomers(Worksheet worksheet,
              SharedStringTable sharedString)
            {
                //Initialize the customer list.
                List<Customer> result = new List<Customer>();

                //LINQ query to skip first row with column names.
                IEnumerable<Row> dataRows =
                  from row in worksheet.Descendants<Row>()
                  where row.RowIndex > 1
                  select row;

                foreach (Row row in dataRows)
                {
                    //LINQ query to return the row's cell values.
                    //Where clause filters out any cells that do not contain a value.
                    //Select returns the value of a cell unless the cell contains
                    //  a Shared String.
                    //If the cell contains a Shared String, its value will be a
                    //  reference id which will be used to look up the value in the
                    //  Shared String table.
                    IEnumerable<String> textValues =
                      from cell in row.Descendants<Cell>()
                      where cell.CellValue != null
                      select
                        (cell.DataType != null
                          && cell.DataType.HasValue
                          && cell.DataType == CellValues.SharedString
                        ? sharedString.ChildElements[
                          int.Parse(cell.CellValue.InnerText)].InnerText
                        : cell.CellValue.InnerText)
                      ;

                    //Check to verify the row contained data.
                    if (textValues.Count() > 0)
                    {
                        //Create a customer and add it to the list.
                        var textArray = textValues.ToArray();
                        Customer customer = new Customer();
                        customer.Name = textArray[0];
                        customer.City = textArray[1];
                        customer.State = textArray[2];
                        result.Add(customer);
                    }
                    else
                    {
                        //If no cells, then you have reached the end of the table.
                        break;
                    }
                }

                //Return populated list of customers.
                return result;
            }
        }

        /// <summary>
        /// Used to store order information for analysis.
        /// </summary>
        public class Order
        {
            //Properties.
            public string Number { get; set; }
            public DateTime Date { get; set; }
            public string Customer { get; set; }
            public Double Amount { get; set; }
            public string Status { get; set; }

            /// <summary>
            /// Helper method for creating a list of orders
            /// from an Excel worksheet.
            /// </summary>
            public static List<Order> LoadOrders(Worksheet worksheet,
              SharedStringTable sharedString)
            {
                //Initialize order list.
                List<Order> result = new List<Order>();

                //LINQ query to skip first row with column names.
                IEnumerable<Row> dataRows =
                  from row in worksheet.Descendants<Row>()
                  where row.RowIndex > 1
                  select row;

                foreach (Row row in dataRows)
                {
                    //LINQ query to return the row's cell values.
                    //Where clause filters out any cells that do not contain a value.
                    //Select returns cell's value unless the cell contains
                    //  a shared string.
                    //If the cell contains a shared string its value will be a
                    //  reference id which will be used to look up the value in the
                    //  shared string table.
                    IEnumerable<String> textValues =
                      from cell in row.Descendants<Cell>()
                      where cell.CellValue != null
                      select
                        (cell.DataType != null
                          && cell.DataType.HasValue
                          && cell.DataType == CellValues.SharedString
                        ? sharedString.ChildElements[
                          int.Parse(cell.CellValue.InnerText)].InnerText
                        : cell.CellValue.InnerText)
                      ;

                    //Check to verify the row contains data.
                    if (textValues.Count() > 0)
                    {
                        //Create an Order and add it to the list.
                        var textArray = textValues.ToArray();
                        Order order = new Order();
                        order.Number = textArray[0];
                        order.Date = new DateTime(1900, 1, 1).AddDays(
                          Double.Parse(textArray[1]) - 2);
                        order.Customer = textArray[2];
                        order.Amount = Double.Parse(textArray[3]);
                        order.Status = textArray[4];
                        result.Add(order);
                    }
                    else
                    {
                        //If no cells, then you have reached the end of the table.
                        break;
                    }
                }

                //Return populated list of orders.
                return result;
            }
        }

    }
}

Tags:

Linq

Type Equivalence Embedded Interop Types

by Brian Keating Fri, April 16 2010 15:26

 

Beginning with the .NET Framework version 4, the common language runtime supports embedding type information for COM types directly into managed assemblies, instead of requiring the managed assemblies to obtain type information for COM types from interop assemblies. Because the embedded type information includes only the types and members that are actually used by a managed assembly, two managed assemblies might have very different views of the same COM type. Each managed assembly has a different Type object to represent its view of the COM type. The common language runtime supports type equivalence between these different views for interfaces, structures, enumerations, and delegates.

Type equivalence means that a COM object that is passed from one managed assembly to another can be cast to the appropriate managed type in the receiving assembly.

NoteNote

Type equivalence and embedded interop types simplify the deployment of applications and add-ins that use COM components, because it is not necessary to deploy interop assemblies with the applications. Developers of shared COM components still have to create primary interop assemblies (PIAs) if they want their components to be used by earlier versions of the .NET Framework.

Type Equivalence

Equivalence of COM types is supported for interfaces, structures, enumerations, and delegates. COM types qualify as equivalent if all of the following are true:

  • The types are both interfaces, or both structures, or both enumerations, or both delegates.

  • The types have the same identity, as described in the next section.

  • Both types are eligible for type equivalence, as described in the Marking COM Types for Type Equivalence section.

Type Identity

Two types are determined to have the same identity when their scopes and identities match, in other words, if they each have the TypeIdentifierAttribute attribute, and the two attributes have matching Scope and Identifier properties. The comparison for Scope is case-insensitive.

If a type does not have the TypeIdentifierAttribute attribute, or if it has a TypeIdentifierAttribute attribute that does not specify scope and identifier, the type can still be considered for equivalence as follows:

Marking COM Types for Type Equivalence

You can mark a type as eligible for type equivalence in two ways:

Tags:

.NET Concurrency

by Brian Keating Fri, April 16 2010 15:25

Optimistic Concurrency

In a multiuser environment, there are two models for updating data in a database: optimistic concurrency, and pessimistic concurrency. The DataSet object is designed to encourage the use of optimistic concurrency for long-running activities such as when you are remoting data and when users are interacting with data.

Pessimistic concurrency involves locking rows at the data source to prevent users from modifying data in a way that affects other users. In a pessimistic model, when a user performs an action that causes a lock to be applied, other users cannot perform actions that would conflict with the lock until the lock owner releases it. This model is primarily used in environments where there is heavy contention for data, where the cost of protecting data with locks is less than the cost of rolling back transactions if concurrency conflicts occur.

Therefore, in a pessimistic currency model, a user who reads a row with the intention of changing it establishes a lock. Until the user has finished the update and released the lock, no one else can change that row. For this reason, pessimistic concurrency is best implemented when lock times will be short, as in programmatic processing of records. Pessimistic concurrency is not a scalable option when users are interacting with data, causing records to be locked for relatively large periods of time.

By contrast, users who use optimistic concurrency do not lock a row when reading it. When a user wants to update a row, the application must determine whether another user has changed the row since it was read. Optimistic concurrency is generally used in environments with a low contention for data. This improves performance as no locking of records is required, and locking of records requires additional server resources. Also, in order to maintain record locks, a persistent connection to the database server is required. Because this is not the case in an optimistic concurrency model, connections to the server are free to serve a larger number of clients in less time.

In an optimistic concurrency model, a violation is considered to have occurred if, after a user receives a value from the database, another user modifies the value before the first user has attempted to modify it.

 

Tags:

LINQPad

by Brian Keating Fri, April 16 2010 11:14

If you've not used nor know what LINQPad is...... tut tut tut

Download it form here

http://www.linqpad.net/  it will make your life easier, infact you'll wonder whatever you did without it...

So how does it help...? try it and see :-)

Tags:

Linq

Declarative Ria Data and Controls

by Brian Keating Wed, March 24 2010 21:27

I'm really loving this declarative approach with silverlight and wpf... (ask me why and I can't tell you ! :-)

Anyway I've just stumbled across a way of managing RiaDataContexts Declaratively
I found it on the Telerik samples.... If you've not looked at these guys controls then check them out!!

 

<navigation:Page xmlns:dataFormToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"  xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
  x:Class="SiteDocs.Loler"
  xmlns="//schemas.microsoft.com/winfx/2006/xaml/presentation">http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
  xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.GridView"
  xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Ria"
  xmlns:e="clr-namespace:SiteDocs.Web.Services"
  xmlns:riaData="clr-namespace:System.Windows.Data;assembly=System.Windows.Controls.Ria"
  mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480" 
  Style="{StaticResource PageStyle}"
>

  <Grid x:Name="LayoutRoot" >
    <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}" >

            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
    
    <Grid x:Name="gridLolerLeft" >
     <Grid.RowDefinitions>
      <RowDefinition />
      <RowDefinition Height="Auto"/>
     </Grid.RowDefinitions>

                    <riaControls:DomainDataSource x:Name="DomainDataSource1" AutoLoad="True" QueryName="GetLolers" PageSize="10">
                        <riaControls:DomainDataSource.DomainContext>
                            <e:LolerContext />
                        </riaControls:DomainDataSource.DomainContext>
                        <riaControls:DomainDataSource.FilterDescriptors>
                            <riaData:FilterDescriptorCollection LogicalOperator="Or" />
                        </riaControls:DomainDataSource.FilterDescriptors>
                    </riaControls:DomainDataSource>

                    <telerik:RadGridView x:Name="RadGridView1" ItemsSource="{Binding Data, ElementName=DomainDataSource1}"
                             Filtering="RadGridView1_Filtering" IsBusy="{Binding IsBusy, ElementName=DomainDataSource1}" />
           <telerik:RadDataPager x:Name="RadDataPager1" Grid.Row="1" Source="{Binding Data, ElementName=DomainDataSource1}" DisplayMode="FirstLastPreviousNextNumeric, Text" IsTotalItemCountFixed="True"/>

    
    </Grid>

                </Grid>
    </ScrollViewer>
  </Grid>

</navigation:Page>

Tags:

RIA Services | Silverlight | WPF

Expression blend visual states

by Brian Keating Tue, March 23 2010 22:57

A few people have asked me what's the easiest way of doing transitions on Silverlight.

One of the easiest ways has to be to use the VisualStateManager with Expression Blend, see screen show for sample logged in state.
If you don't know how to use this tool then start watching a few vids!

 

To change between states you can use this code..

 

 

if (WebContext.Current.User.IsAuthenticated)
{
    VisualStateManager.GoToState(this, (WebContext.Current.Authentication is WindowsAuthentication) ? "windowsAuth" : "LoggedIn", true);
}
else
{
    VisualStateManager.GoToState(this, "LoggedOut", true);
}


Tags:

Blend | Silverlight

Providing Security in RIA services

by Brian Keating Tue, March 23 2010 21:18

If you wish to prevent clients accessing your data

[RequiresAuthentication]
[EnableClientAccess()]
public class LolerService : LinqToSqlDomainService<LolerModelDataContext>

Tags:

Silverlight | Sql

Popups in wpf

by Brian Keating Wed, March 17 2010 17:14

Here is come code to show a popup in wpf, i've nothing in the popup at the moment, just a gradient background and border.

<Popup Name="popup1" 
   Width="{Binding ElementName=bdrCalendar, Path=ActualWidth, Converter={StaticResource MarginValueConverter}}"
   Height="150"
   Placement="Center"
   PopupAnimation="Scroll"
   AllowsTransparency="True"
   PlacementTarget="{Binding ElementName=bdrCalendar}"
   MouseDown="popup1_MouseDown" >
 <ctrls:PopupContent />
</Popup>

 

 

 

 

Tags:

WPF

RIA Services

by Brian Keating Mon, March 15 2010 11:15

Over the w/end I was helping a mate with his Data-driven Silverlight app.

I was gobsmacked that his developer spent days and weeks writing plumbing code, hand coding infrastructure code and even worse my friend had to pay for it.
Being able to focus on the business needs is important so having a development platform that better enables that focus and increased productivity is an absolute must.

The solution to this problem is codenamed Alexandria i.e. .NET RIA Services, this technology provides a set of server components and ASP.NET extensions that ease the n-tier development process, making your applications almost as easy to develop as if they were running on a single tier, In addition, services such as authentication, roles and profile management are provided. The combination of client and server enhancements to Silverlight 3 and ASP.NET along with the addition of .NET RIA Services, streamline the end-to-end experience of developing data-driven Web applications also known as Rich Internet Applications, or RIAs.

I’m not going to show you how to do it as there are many-many training resources available but a good place to start is here: http://silverlight.net/getstarted/riaservices/

So if you find yourself writing needless plumbing code for a DAL in Silverlight, then spend some time figuring RIA services out!
(Spend some get some diesel for that digger and opposed to grabbing a shovel and diving in!!)

 

 

Tags:

Silverlight | RIA Services

Filtering data in Silverlight

by Brian Keating Sat, March 06 2010 18:23

Ever want to filter data in Silverlight? here's a simple example that uses a lambda expression to search on name (case sensitive)

 

ComboBox cbx = ((ComboBox)sender);

ICollectionView dataView =
            CollectionViewSource.GetDefaultView(this.DataContext);
if (!string.IsNullOrEmpty(cbx.Text))
    dataView.Filter = f => ((Job)f).Name.Contains(cbx.Text);
else
    dataView.Filter = null;

Tags: , ,

Silverlight | WPF