Welcome to MSDN Blogs Sign in | Join | Help

Solution - Novice Challenge 7: Switcheroo

This was an interesting challenge. As with just about any coding challenge, there were multiple ways of accomplishing this task. For the challenges so far we’ve seen code ranging three lines long to code 20 lines long, with the outcome of both being identical. We usually would never presume to tell anyone which way is the right way; after all, if it works the way it’s supposed to and if you can understand what the code is doing,  well, who are we to say what’s better?

On the other hand, you may come up with a solution that works and makes perfect sense to you, only to then see the solution someone else came up with and think “Wow, that’s better than what I did.”

Chances are you won’t be saying that about the solution we came up with.

Why would we say that? Because we saw some solutions from you guys that we thought were much better than the one we came up with. So what we’re going to do here is take you through our solution, then show you the solution several people submitted that we think is better. You can judge for yourself.

Although, to be honest, you’d be crazy to think that out solution is the better one.

Speaking of which, here is our solution:

Public Sub RowColumnSwap()

 

Dim i As Integer

Dim j As Integer

Dim objRange As Range

Dim intRows As Integer

Dim intColumns As Integer

Dim s1 As Worksheet

Dim s2 As Worksheet

 

i = 1

j = 1

 

'Get references to the data and the two worksheets

Set objRange = Worksheets("Sheet1").UsedRange

Set s1 = Worksheets("Sheet1")

Set s2 = Worksheets("Sheet2")

 

'Get the number of rows and columns in the table

intRows = objRange.Rows.Count

intColumns = objRange.Columns.Count

 

'Cycle through the columns

While (i <= intColumns)

 

    'Cycle through the rows within the column

    While (j <= intRows)

   

        'Move the values from i,j in Sheet1 to j,i in Sheet2

        s2.Cells(i, j).Value = s1.Cells(j, i).Value

        j = j + 1

       

    Wend

   

    i = i + 1

    j = 1

   

Wend

 

'Show Sheet2

s2.Activate

 

End Sub

 

We start out by declaring a bunch of variables, then retrieve object references to the used range (the range of cells with data in them) and the two worksheets:

Set objRange = Worksheets("Sheet1").UsedRange

Set s1 = Worksheets("Sheet1")

Set s2 = Worksheets("Sheet2")

Before we can swap rows and columns, we need to find out how many rows and columns we’re working with. We can do that by checking the Count property of the Rows and Columns objects in our range of data:

intRows = objRange.Rows.Count

intColumns = objRange.Columns.Count

The next part might seem a little complicated (which is why it’s not as good as the other solutions). What we’re going to do is turn all the rows into columns, and all the columns into rows. Here’s how we’re going to do that:

1.       Loop through the columns on Sheet1 one at a time.

2.       Within each column, loop through the rows in that column.

3.       Copy the value from each cell at column, row (such as cell 1, 4 – cell A4) in Sheet1 to the corresponding cell row, column (i.e., cell 4, 1 – cell D1) in Sheet2.

Make sense? Let’s walk through it. We start with a While loop that continues while our column counter (i) is less than or equal to the total number of columns we’re copying:

While (i <= intColumns)

Within that column we loop through the rows, continuing through the rows of that column while our row counter (j) is less than or equal to the total number of rows:

While (j <= intRows)

As we just mentioned, our counters contain the column (i) and the row (j) we’re copying. So we simply assign the value of the cell at that location in Sheet1 to the opposite cell in Sheet2, like this:

s2.Cells(i, j).Value = s1.Cells(j, i).Value

We then increment our row counter and continue through the rows. When we’ve reached the last row, we reset our row counter and start on the next column:

i = i + 1

j = 1

The last thing we do is show off our handiwork by making Sheet2 the active worksheet:

s2.Activate

And we’re done. Now, there’s really nothing wrong with this solution: at the very least, you get to practice your nested loops (loops within loops). But once you’ve had all the fun you can handle with loops and nested loops, how about letting Excel do the work for you? Take a look at this revised solution:

Public Sub RowColumnSwap()

 

Dim objRange As Range

Dim s2 As Worksheet

 

'Get references to the data and the two worksheets

Set objRange = Worksheets("Sheet1").UsedRange

Set s2 = Worksheets("Sheet2")

 

objRange.Copy

s2.Activate

s2.Range("A1").PasteSpecial Transpose:=True

 

 

'Show Sheet2

's2.Activate

 

End Sub

 

Wow, that looks a little simpler, doesn’t it? We start out about the same way we started the first time, declaring a couple variables (although not nearly as many) and retrieving references to the used range in Sheet1 and to the Sheet2 worksheet itself.

Next we call the Copy method on the used range to copy the data from Sheet1 to the Clipboard:

objRange.Copy

After that we call the Activate method on Sheet2 to, well, to make that worksheet the active worksheet:

s2.Activate

The last thing we do is to call the PasteSpecial method:

s2.Range("A1").PasteSpecial Transpose:=True

As you can see, we call this command on a Range object in Sheet2. We use a range consisting just of cell A1 simply because this is the cell where we want to start pasting the data from the Clipboard – the PasteSpecial method will fill in as many cells as it needs from that point.

Notice the parameter we pass to PasteSpecial:

Transpose:=True

If you take a look at the Excel Object Model Reference on MSDN you’ll discover that setting the Transpose parameter to True will “transpose rows and columns when the range is pasted.” And guess what? That’s just exactly what we want to do.

Sure, this wasn’t nearly as much fun as nested While loops. But it was easier.

Published Tuesday, April 28, 2009 9:54 PM by PaloozaTeam

Comments

Anonymous comments are disabled
 
Page view tracker