Split data into multiple sheets using macro [Solved/Closed]

- May 31, 2011 at 02:31 AM - Latest reply:
Posts
4481
Registration date
Thursday January 28, 2010
Status
Contributor
Last seen
January 6, 2016
- May 31, 2011 at 09:31 PM
Hello,





I have an excel sheet with the data in following manner.


a b c d
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4


e f g h
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
5 5 5 5


i j k l
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
5 5 5 5
6 6 6 6


Above there is a blank row after each table data. Now I want to split this data from one sheet to multiple sheets like below and also make the first row BOLD in each sheet which represents the table heading.


DataSheet1
a b c d
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4


DataSheet2
e f g h
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
5 5 5 5


DataSheet3
i j k l
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
5 5 5 5
6 6 6 6


Please advise how I can do it using macro in excel.
See more 

16 replies

Best answer
Posts
4481
Registration date
Thursday January 28, 2010
Status
Contributor
Last seen
January 6, 2016
- May 31, 2011 at 06:20 AM
3
Thank you
make a back copy of the file
open excel
press alt + f11 at the same time
click on insert and insert a new module
paste the code below (after the instructions)
run the code by executing routine doSplitData

It will create or (recreate sheets) titled "datasheet1", "datasheet2" etc


Sub doSplitData()
    
  Dim lMaxRows                   As Long
  Dim sSheet                     As String
  Dim lStartRow                  As Long
  Dim lEndRow                    As Long
  Dim sFinalSheet                As String
  Dim iSheetCount                As Integer
  
   sSheet = "Sheet1"
   sFinalSheet = "DataSheet"
   iSheetCount = 0
   Application.ScreenUpdating = False
   With Sheets(sSheet)
      lMaxRows = getItemRowLocation("*", .Cells)
      lStartRow = 0
      lStartRow = getItemRowLocation("*", .Range(.Cells(lStartRow + 1, "A"), .Cells(lMaxRows, "A")), , False)
      Do While (lStartRow > 0)
         lEndRow = getItemRowLocation(vbNullString, .Range(.Cells(lStartRow + 1, "A"), .Cells(lMaxRows, "A")), , False)
    
         If (lEndRow > 0) _
         Then
            
         Else
            lEndRow = lMaxRows
         End If
         
         On Error Resume Next
         iSheetCount = iSheetCount + 1
         Application.DisplayAlerts = False
         Sheets(sFinalSheet & iSheetCount).Delete
         Application.DisplayAlerts = True
         Sheets.Add
         ActiveSheet.Name = sFinalSheet & iSheetCount
         Application.CutCopyMode = False
         .Rows(lStartRow & ":" & lEndRow).Copy
         With Sheets(sFinalSheet & iSheetCount)
            .Cells(1, 1).PasteSpecial
            Rows(1).Font.Bold = True
         End With
         Application.CutCopyMode = False
         lStartRow = getItemRowLocation("*", .Range(.Cells(lEndRow + 1, "A"), .Cells(lMaxRows + 1, "A")), , False)
      Loop
      Application.ScreenUpdating = True
   End With
End Sub
Public Function getItemRowLocation(sLookFor As String, _
                            rngSearch As Range, _
                            Optional bFullString As Boolean = True, _
                            Optional bLastOccurance As Boolean = True) As Long
' get last use row on the sheet

   Dim Cell             As Range
   Dim iLookAt          As Integer
   Dim iSearchDir       As Integer
   
   If (bFullString) _
   Then
      iLookAt = xlWhole
   Else
      iLookAt = xlPart
   End If
   
   If (bLastOccurance) _
   Then
      iSearchDir = xlPrevious
   Else
      iSearchDir = xlNext
   End If
   
   With rngSearch
      If (bLastOccurance) _
      Then
         Set Cell = .Find(sLookFor, .Cells(1, 1), xlValues, iLookAt, xlByRows, iSearchDir)
      Else
         Set Cell = .Find(sLookFor, .Cells(.Rows.Count, .Columns.Count), xlValues, iLookAt, xlByRows, iSearchDir)
      End If
   End With
   
   If Cell Is Nothing Then
      getItemRowLocation = 0
   Else
      getItemRowLocation = Cell.Row
   End If
   Set Cell = Nothing
End Function

Thank you, rizvisa1 3

Something to say? Add comment

CCM has helped 1634 users this month

0
Thank you
I am the one who asked this question.

Just want to add that the heading of each table will remain same/constant but the number of rows below each table heading will be dynamic.
0
Thank you
Hi Rizvisa,

Many thanks for the script. But since there are many blank rows later in my output I am not getting the desired results. Please could you help to modify the script in such a way that it will execute in below fashion.

There are 13 set of tables in the first sheet. Each one will have start and end indicator as below.

JVMStart
a b c d
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
JVMEnd

JDBCStart
e f g h
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
5 5 5 5
JDBCEnd

JMSStart
i j k l
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
5 5 5 5
6 6 6 6
JMSEnd

MonitorPolicyStart
...
...
...
MonitorPolicyEnd

WebContainerStart
...
...
...
WebContainerEnd

VirtualHostStart
...
...
...
VirtualHostEnd

AdminConsoleStart
...
...
...
AdminConsoleEnd

ClusterStart
...
...
...
ClusterEnd

NodeGroupStart
...
...
...
NodeGroupEnd

PMIStart
...
...
...
PMIEnd

IPFilteringStart
...
...
...
IPFilteringEnd

AppResourcesStart
...
...
...
AppResourcesEnd

SecurityStart
...
...
...
SecurityEnd


Now I want 13 sheets to be created with their respective names like below. i.e. copying all the rows after and before the JVMStart and JVMEnd and putting it into new sheet with the name JVM. Similarly for rest of the tables.

"JVM" # This will be the sheet name - just need to remove the start/end suffix and use the indicator as the name
a b c d
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4

"JDBC"
e f g h
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
5 5 5 5

"JMS"
i j k l
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
5 5 5 5
6 6 6 6

and so on for the rest...

Many Thanks and appreciate your wonderful help.
Posts
4481
Registration date
Thursday January 28, 2010
Status
Contributor
Last seen
January 6, 2016
- May 31, 2011 at 11:48 AM
Well sorry that it did not still solve your issue. I guess I will wait till you are able to post the workbook. Based on sample data it worked for me. Obviously some thing is not fitting right for you. Only way for me to know what would be to actually see a workbook with how it is now and how you would like to see. may be when you get home, you can post sample workbook. When you do post the book, post both version of data both with multiple blank row that you say are not handled properly by this code and the other one. As for me, multiple blank rows works perfectly fine as they are ignored. only rows with data are copied
Hi Rizvisa,

Appreciate your time and efforts in solving my problem. I have uploaded both input and expected output xls sheets. Please download the same from below.

http://wikisend.com/download/933108/input.xlsx
http://wikisend.com/download/490438/output.xlsx
Posts
4481
Registration date
Thursday January 28, 2010
Status
Contributor
Last seen
January 6, 2016
- May 31, 2011 at 06:20 PM
HI Suhas.
Ok first allow me vent off. A good representative of data is a helpful for any one trying to help. Based on your books, it seem that with in each group you may have blank rows. This information how the data is comes out drip drip, which is real frustrating and time wasting. First it was blank rows is a delimiter then it became that in column A only, there might be blank cells and yet they would still form the part of the group. and now your sample book that I was asking earlier seem to show that within each group you may have blank rows. Most, if not all people on any forum, not just this one, are just helping out of their own time for free. I understand that you most probably did not do intentionally it but please when you ask a question on any forum, please do provide as complete, and detailed and correct information as is possible It saves times and effort of any one who would be trying to help. Ok now that I have let off my pent up steam, here is your updated macro

Sub doSplitData()
     
  Dim lMaxRows                   As Long
  Dim sSheet                     As String
  Dim lStartRow                  As Long
  Dim lEndRow                    As Long
  Dim sFinalSheet                As String
  Dim lMaxCols                   As Integer
   
   sSheet = "Sheet1"
   Application.ScreenUpdating = False
   With Sheets(sSheet)
   
      lMaxCols = getItemLocation("*", .Cells, bFindRow:=False)
      lMaxRows = getItemLocation("*", .Cells)
       
      lStartRow = 0
      lStartRow = getItemLocation("*Start", .Range(.Cells(lStartRow + 1, 1), .Cells(lMaxRows, 1)), , False)
      Do While (lStartRow > 0)
         sFinalSheet = Trim(.Cells(lStartRow, 1))
         sFinalSheet = Left(sFinalSheet, Len(sFinalSheet) - Len("Start"))
         lEndRow = getItemLocation(sFinalSheet & "End", .Range(.Cells(lStartRow + 1, 1), .Cells(lMaxRows, 1)), , False)
         If (lEndRow = 0) Then lEndRow = lMaxRows
         Application.DisplayAlerts = False
         On Error Resume Next
         Sheets(sFinalSheet).Delete
         Err.Clear
         On Error GoTo 0
         Application.DisplayAlerts = True
         Sheets.Add
         ActiveSheet.Name = sFinalSheet
         Application.CutCopyMode = False
         .Range(.Cells(lStartRow + 1, 1), .Cells(lEndRow - 1, lMaxCols)).Copy
         With Sheets(sFinalSheet)
            .Cells(1, 1).PasteSpecial
            .Rows(1).Font.Bold = True
         End With
         Application.CutCopyMode = False
         lStartRow = getItemLocation("*Start", .Range(.Cells(lEndRow + 1, 1), .Cells(lMaxRows, 1)), , False)
      Loop
      Application.ScreenUpdating = True
   End With
End Sub

Public Function getItemLocation(sLookFor As String, _
                                rngSearch As Range, _
                                Optional bFullString As Boolean = True, _
                                Optional bLastOccurance As Boolean = True, _
                                Optional bFindRow As Boolean = True) As Long
    
   Dim Cell             As Range
   Dim iLookAt          As Integer
   Dim iSearchDir       As Integer
   Dim iSearchOdr       As Integer
    
   If (bFullString) _
   Then
      iLookAt = xlWhole
   Else
      iLookAt = xlPart
   End If
   If (bLastOccurance) _
   Then
      iSearchDir = xlPrevious
   Else
      iSearchDir = xlNext
   End If
   If Not (bFindRow) _
   Then
      iSearchOdr = xlByColumns
   Else
      iSearchOdr = xlByRows
   End If
    
   With rngSearch
      If (bLastOccurance) _
      Then
         Set Cell = .Find(sLookFor, .Cells(1, 1), xlValues, iLookAt, iSearchOdr, iSearchDir)
      Else
         Set Cell = .Find(sLookFor, .Cells(.Rows.Count, .Columns.Count), xlValues, iLookAt, iSearchOdr, iSearchDir)
      End If
   End With
    
   If Cell Is Nothing Then
      getItemLocation = 0
   ElseIf Not (bFindRow) _
   Then
      getItemLocation = Cell.Column
   Else
      getItemLocation = Cell.Row
   End If
   Set Cell = Nothing

End Function

THanks you so much rizvisa. Appologies for the confusion it created about the data output.

Now the script works awesome - appreciate your super duper help.
Posts
4481
Registration date
Thursday January 28, 2010
Status
Contributor
Last seen
January 6, 2016
- May 31, 2011 at 09:31 PM
you are welcome