How to make a dynamic link to a pivot table value? - excel

On tab1 I have a pivot table . When I double click subtotal number 256 on that pivot table, a new worksheet pops up with the details. Everything is just as expected.
On tab2, I have a formula in the field A1 . This formula refers to the subtotal value in the pivot (from tab1)
=GETPIVOTDATA("theId",tab1!$A$1)
A1 shows 256 . . . exactly as in the pivot table .
I need to be able to doulble click this A1 field and see a pop up worksheet with the details (as if I was clicking the pivot table)
The problem is GETPIVOTDATA returns a value only and no link or indirect reference
How can I do this ?

Sorry for the delay, but the weekend was in the middle.
Well here is my answer to how to show the data from a pivot, just with doble click inside a cell, in another sheet that have, the GETPIVOTDATA formula.
Note that in my pivot, I set to "Repeat all items labels" and use a old style pivot.
See the pictures:
For repeat all items labels
and the old style works better for me, and most of all, the macro (VBA)
That been said, let's code!!
All this inside a regular module.
Sub getDataFromFormula(theFormulaSht As Worksheet, formulaCell As Range)
Dim f
Dim arrayF
Dim i
Dim L
Dim iC
Dim newArrayF() As Variant
' Dim rowLables_Sort()
' Dim rowLables_Sort_i()
Dim T As Worksheet
Dim rowRange_Labels As Range
Dim shtPivot As Worksheet
Dim shtPivotName
Dim thePivot As PivotTable
Dim numRows
Dim numCols
Dim colRowRange As Range
Dim colRowSubRange As Range
Dim First As Boolean
Dim nR
Dim nC
Dim myCol
Dim myRow
Dim theRNG As Range
Set T = theFormulaSht 'the sheet where the formula is
'#####################################
'my example formula
'=GETPIVOTDATA("EURO",P!$A$3,"Descripcion","Ingresos Netos de Terceros ,","Mes","July","CuentaCrest","310100","Descripción Crest","Net revenue third parties","Producto","AFR","SubProducto","AFRI","TM1","Net Revenue")
'#####################################
T.Activate 'go!
f = formulaCell.Formula 'get the formula
f = Replace(f, "=GETPIVOTDATA", "") 'delete some things...
f = Replace(f, Chr(34), "")
f = Replace(f, ",,", ",") 'in my data, there is ,, and I need to fix this...
f = Right(f, Len(f) - 1) 'take the formual without parentesis.
f = Left(f, Len(f) - 1)
'####################################
'Restult inside "f"
'EURO,P!$A$3,Descripcion,Ingresos Netos de Terceros ,Mes,July,CuentaCrest,310100,Descripción Crest,Net revenue third parties,Producto,AFR,SubProducto,AFRI,TM1,Net Revenue
'####################################
arrayF = Split(f, ",")
'####################################
'Restult inside arrayF
'EURO,P!$A$3,Descripcion,Ingresos Netos de Terceros ,Mes,July,CuentaCrest,310100,Descripción Crest,Net revenue third parties,Producto,AFR,SubProducto,AFRI,TM1,Net Revenue
'####################################
shtPivotName = arrayF(1) 'set (just) the name of the sheet with the pivot
shtPivotName = Left(shtPivotName, InStr(1, shtPivotName, "!") - 1)
Set shtPivot = Sheets(shtPivotName) 'set the var with the sheet that contents the pivot
Set thePivot = shtPivot.PivotTables(1) 'store the pivot inside
If shtPivot.Visible = False Then 'if the sheet with the pivot is hidden... set visible.
shtPivot.Visible = xlSheetVisible
End If
shtPivot.Activate 'go there!
numRows = thePivot.RowRange.Rows.Count - 1 'the number of rows of the row Range
numCols = thePivot.RowRange.Columns.Count 'here the columns of the same range
Set rowRange_Labels = thePivot.RowRange.Resize(1, numCols)
'with Resize get jus the labels above the RowRange (see the picture (1))
iC = -1
First = True
For Each i In rowRange_Labels 'run the labels
iC = -1 'set the counter
If First Then 'check the flag to see if is the firt time...
First = False 'set the flag to FALSE to go the other part of the IF next time
Set colRowRange = Range(Cells(i.Row, i.Column), Cells(i.Row + numRows - 1, i.Column))
Do
iC = iC + 1 'just to set the counter
Loop While arrayF(iC) <> i.Value 'stop when gets equals and keep the counter
'in the array the values are just strings,
'but we know that is key-value pairs thats why adding +1 to iC we get the real info
'below the label
nR = colRowRange.Find(arrayF(iC + 1)).Row 'just used here
nC = WorksheetFunction.CountIf(colRowRange, arrayF(iC + 1)) + nR - 1 'here we count to set the range
Set colRowSubRange = Range(Cells(nR, i.Column), Cells(nC, i.Column)) 'set the range
myRow = colRowSubRange.Row 'here we get the row of the value
Else
Do 'this is simpler
iC = iC + 1
Loop While arrayF(iC) <> i.Value 'againg...
nR = colRowSubRange.Offset(, 1).Find(arrayF(iC + 1)).Row 'use the SubRange to get others subranges
nC = WorksheetFunction.CountIf(colRowSubRange.Offset(, 1), arrayF(iC + 1)) + nR - 1
Set colRowSubRange = Range(Cells(nR, i.Column), Cells(nC, i.Column))
myRow = colRowSubRange.Row 'idem
End If
Next i
numCols = thePivot.DataBodyRange.Columns.Count 'other part of the pivot... (see the picture (2))
Set theRNG = thePivot.DataBodyRange.Resize(1, numCols) 'just take the above labels
Set theRNG = theRNG.Offset(-1, 0)
iC = -1
For Each L In thePivot.ColumnFields 'for every label...
Do
iC = iC + 1
Loop While L <> arrayF(iC) 'idem
myCol = theRNG.Find(arrayF(iC + 1), , , xlWhole).Column
'always will be just one column...
Next L
Cells(myRow, myCol).ShowDetail = True 'here is the magic!!! show all the data
End Sub
And inside the Worksheet code this:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Left(Target.Formula, 13) = "=GETPIVOTDATA" Then 'Check if there a formula GetPivotData
getDataFromFormula Sheets(Me.Name), Target
End If
End Sub
See this picture to understand what happends to the formula:
The formula is split it as you can see f, into arrayF.
I'm sure you will need to do some changes, but this is very functional and basic, and will be easy to findout what you need.
Also:
This part of code helps me a lot to understand what the pivot had. Using the same data and pivot, I ran the code:
Sub rangePivot()
Dim Pivot As PivotTable
Dim rng As Range
Dim P As Worksheet
Dim D As Worksheet
Dim S As Worksheet
Dim i
Set P = Sheets("P") 'the sheet with the pivot
Set D = Sheets("D") 'the sheet with the data
Set S = Sheets("S") 'the sheet with the cells with the formula
S.Activate 'go
Set Pivot = P.PivotTables("PivotTable1") 'store the pivot here...
For i = 1 To Pivot.RowFields.Count
Cells(i, 1).Value = Pivot.RowFields(i)
Next i
For i = 1 To Pivot.ColumnFields.Count
Cells(i, 2).Value = Pivot.ColumnFields(i)
Next i
For i = 1 To Pivot.DataFields.Count
Cells(i, 3).Value = Pivot.DataFields(i)
Next i
For i = 1 To Pivot.DataLabelRange.Count
Cells(i, 4).Value = Pivot.DataLabelRange.Address(i)
Next i
For i = 1 To Pivot.DataLabelRange.Count
Cells(i, 4).Value = Pivot.DataLabelRange.Address(i)
Next i
For i = 1 To Pivot.DataFields.Count
Cells(i, 5).Value = Pivot.DataFields(i)
Next i
For i = 1 To Pivot.DataFields.Count
Cells(i, 5).Value = Pivot.DataFields(i)
Next i
For i = 1 To Pivot.DataFields.Count
Cells(i, 5).Value = Pivot.DataFields(i)
Next i
For i = 1 To Pivot.DataBodyRange.Count
Cells(i, 6).Value = Pivot.DataBodyRange.Address(i)
Next i
For i = 1 To Pivot.DataLabelRange.Count
Cells(i, 7).Value = Pivot.DataLabelRange.Address(i)
Next i
Cells(1, 8).Value = Pivot.ColumnGrand
Cells(1, 9).Value = Pivot.RowRange.Address
Cells(1, 11).Value = Pivot.TableRange1.Address
Cells(1, 12).Value = Pivot.TableRange2.Address
End Sub
And, as usual, if you need som help & improvement contact me. Hope this help other too.

If you want to do VBA you could set up an event like here:
http://www.ozgrid.com/forum/showthread.php?t=49050
Once you have that set up you need to develop some code that determines where the subtotal cell is (because those are prone to change). Once you have that address you can use Range([subtotal]).ShowDetail = True

Related

Loop through filtered list of cells to check if value appears in another column then copy/paste

Need some help with my macro. What I need is to loop through a filterable list of IDs in Sheet2 and match them to where the ID is contained in Column 16 on Sheet 1. Then copy over the whole matched row in Sheet1 over to a Sheet3.
Here's what Sheet2 looks like, generally (filtering by things like Status, etc.):
ID
Summary
Created On
Status
1234567
Text
Date
Done
2345678
Text
Date
In Progress
And Sheet1 (*note the ID -> ID2 match):
ID
Summary
Created On
Status
ID2
#######
Text
Date
Done
1234567, #######, #######
#######
Text
Date
In Progress
#######, 2345678
I used this thread here (Code needed to loop through column range, check if value exists and then copy cells) for a process of pairing in the same workbook that does not need to be filtered, and it seems to work just fine. However, my code in this instance is not pairing the amount of rows correctly nor is it pairing with the correct IDs either. I think something may be off with the pairing process with filtering in the mix?
My code so far:
Public Sub PairingBackTEST()
Dim WS As Worksheet
Set WS = Sheets("Sheet1")
'Clears Sheet 3
Sheets("Sheet3").Activate
Sheets("Sheet3").Cells.Clear
' Get the number of used rows for each sheet
Dim RESULTBlocked As Integer, Blockers As Integer
RESULTBlocked = WS.AutoFilter.Range.Columns(1).SpecialCells(xlCellTypeVisible).Cells.Count
Debug.Print RESULTBlocked
Blockers = Worksheets(1).Cells(1048576, 1).End(xlUp).Row
Debug.Print Blockers
RESULTBlockers = Worksheets(4).Cells(1048576, 1).End(xlUp).Row
'Set date/time format for Created On and Due Date columns
Sheets("Sheet3").Activate
Sheets("Sheet3").Columns("H:H").Select
Selection.NumberFormat = "[$-en-US]m/d/yy h:mm AM/PM;#"
Sheets("Sheet3").Columns("I:I").Select
Selection.NumberFormat
'Pairing
With Worksheets(1)
'Loop through Sheet2
For i = 1 To Blockers
'Loop through Sheet1
For j = 1 To RESULTBlocked
If InStr(1, .Cells(i, 16), WS.Cells(j, 1), vbBinaryCompare) > 0 Then
' If a match is found:
RESULTBlockers = RESULTBlockers + 1
For k = 1 To 17 'How ever many columns there are
Sheets("Sheet3").Cells(RESULTBlockers, k) = .Cells(i, k)
Next
Exit For
Else
End If
Next j
Next i
End With
'Prepare headers on RESULT Blocked
Sheets("Sheet1").Rows(1).Copy
Sheets("Sheet3").Range("A1").PasteSpecial
I'd maybe try an approach like this:
Public Sub PairingBackTEST()
Dim wb As Workbook
Dim wsList As Worksheet, wsCheck As Worksheet, wsResults As Worksheet
Dim lrList As Long, lrCheck As Long, c As Range, cDest As Range, id, m
'use workbook/worksheet variables for clarity, and to avoid repetition...
Set wb = ThisWorkbook
Set wsList = wb.Worksheets("Sheet2")
Set wsCheck = wb.Worksheets("Sheet1")
Set wsResults = wb.Worksheets("Sheet3")
'no need for activate/select here
With wsResults
.Cells.Clear
.Columns("H:H").NumberFormat = "[$-en-US]m/d/yy h:mm AM/PM;#"
'.Columns("I:I").NumberFormat = ??? this is missing in your posted code
wsCheck.Rows(1).Copy .Range("A1") 'copy headers
End With
Set cDest = wsResults.Range("A2") 'first destination row on result sheet
For Each c In wsList.AutoFilter.Range.Columns(1).SpecialCells(xlCellTypeVisible).Cells
id = c.Value
'you can use match in place of looping as long as there's only one row to find
m = Application.Match("*" & id & "*", wsCheck.Columns(16), 0)
If Not IsError(m) Then
If m > 1 Then 'avoid matching on header...
cDest.Resize(1, 17).Value = wsCheck.Cells(m, 1).Resize(1, 17).Value
Set cDest = cDest.Offset(1, 0) 'next row on results sheet
End If
End If
Next c
End Sub

Conditional copying from a table in Excel

I'm trying to copy to both debit/credit columns to other tables which match only the respective account value i.e. all Cash entries go to a Cash Account table, etc. I'll also need a way to omit those that have already been copied (so some check column will have to be referenced).
but I'm unclear how to translate this into VBA.
Here's a visual from the worksheet:
And my VBA code so far (MyAdd being a function that copies the range to another specified table)
Sub CopyRange()
For Each c In Range("Journal").Cells
If c.Value = "Cash" Then
If Range("Journal[#[Account 1]]").Value = "Cash" Then MyAdd "Cash_Account", Range(c.Offset(0, 2), c.Offset(0, 3))
Else: MyAdd "Cash_Account", Range(c.Offset(0, 1), c.Offset(0, 2))
Next
End Sub
I'm not sure why you'd want to do this. It would seem there is another end goal in mind. However, to do what you're asking in VBA can be done with the below code.
Sub GetNewColumnOfData()
Dim Table As ListObject
Dim TargetRange As Range
Dim Index As Long
Dim Values As Variant
Set Table = ThisWorkbook.Worksheets("Sheet3").ListObjects("Journal")
Set TargetRange = ThisWorkbook.Worksheets("Sheet3").Range("G1")
ReDim Values(1 To Table.ListRows.Count, 1 To 1)
For Index = 1 To Table.ListRows.Count
If Table.ListColumns("Account 1").DataBodyRange(Index, 1).Value = "Cash" Then
Values(Index, 1) = 1
ElseIf Table.ListColumns("Account 2").DataBodyRange(Index, 1).Value = "Cash" Then
Values(Index, 1) = 2
End If
Next Index
TargetRange.Resize(Table.ListRows.Count, 1).Value = Values
End Sub
Define your range/table names accordingly.
Using Zack's solution, I have created my solution this way - in case anyone wants to follow my work and improve upon it:
Sub GetNewColumnOfData()
Dim Table As ListObject
Dim TargetRange As Range
Dim Index As Long
Dim Account As String
Set Table = Range("Journal").ListObject
For Index = 1 To Table.ListRows.Count
If Not IsEmpty(Table.ListColumns("Account 1").DataBodyRange(Index, 1)) And IsEmpty(Table.ListColumns("*").DataBodyRange(Index, 1)) Then
Account = Table.ListColumns("Account 1").DataBodyRange(Index, 1).Value
Table.ListColumns("*").DataBodyRange(Index, 1).Value = "*"
MyAdd Account, Range(Table.ListColumns("Debit").DataBodyRange(Index, 1), Table.ListColumns("Credit").DataBodyRange(Index, 1))
ElseIf Not IsEmpty(Table.ListColumns("Account 2").DataBodyRange(Index, 1)) And IsEmpty(Table.ListColumns("*").DataBodyRange(Index, 1)) Then
Account = Table.ListColumns("Account 2").DataBodyRange(Index, 1).Value
Table.ListColumns("*").DataBodyRange(Index, 1).Value = "*"
MyAdd Account, Range(Table.ListColumns("Debit").DataBodyRange(Index, 1), Table.ListColumns("Credit").DataBodyRange(Index, 1))
End If
Next Index
End Sub
The MyAdd function was derived elsewhere on this site but I quote it here for ease of reference:
Sub MyAdd(ByVal strTableName As String, ByRef arrData As Variant)
Dim tbl As ListObject
Dim NewRow As ListRow
Set tbl = Range(strTableName).ListObject
Set NewRow = tbl.ListRows.Add(AlwaysInsert:=True)
' Handle Arrays and Ranges
If TypeName(arrData) = "Range" Then
NewRow.Range = arrData.Value
Else
NewRow.Range = arrData
End If
End Sub
Note I put this code in a module for the Workbook - and all the Ranges (tables/lists) are by default Workbook named ranges - hence accessible without needing to specify the sheets they are on.

Find match value Excel cell from a row

This is an Excel problem.
I have an Excel Rows with the following values:
cell value 1, 2, x, ,1=,2=, ,x=,2
cell address a1,b1,c1,d1,e1,f1,g1,h1,i1
I want to get all non-empty cell addresses from the above row.
i.e.
a1,b1,c1,e1,f1,h1,i1
Is it possible using vba/vbs to do the job?
thank you very much
You can use .SpecialCells(xlCellTypeConstants)
To demonstrate, run this, and observe result in the Imediate window
Sub demo()
Dim rng As Range, rNonEmpty As Range
Set rng = [A1:I1]
Set rNonEmpty = rng.SpecialCells(xlCellTypeConstants)
Debug.Print rNonEmpty.Address
End Sub
The following code will check an area of 10 rows by 1000 columns and finally will show the addresses of the non blank cells in cell A20:
Sub no_blank_cells()
Dim wks As Worksheet
Set wks = ActiveSheet
m = ""
maxrows = 10
maxcolumns = 1000
For i = 1 To maxrows
For j = 1 To maxcolumns
a = Cells(i, j)
If a <> "" Then
m = m & Cells(i, j).Address(RowAbsolute:=False, ColumnAbsolute:=False) & ", "
End If
Next j
Next i
msg = MsgBox(m, vbInformation)
wks.Cells(20, 1) = m
End Sub
If you want to change the area to be searched, modify the value of the variables maxrowsand maxcolumns.
Sub WriteNonNulValue()
'/*SELECT SHEET TO ANALIZE*/
Worksheets("Sheet1").Select
'/*SELECT ROW TO READ*/
Row_to_read = 1
'/*SELECT ROW IN WHICH WRITE*/
Row_to_write = 2
'/*NUMBER OF COLUMNS TO ANALIZE*/
Columns_to_analize = 11
'/*COUNTER WRITE*/
Columns_to_write = 1
For i = 1 To Columns_to_analize
If Trim(Cells(Row_to_read, i)) <> "" Then
'/*WRITE ADDRESS NO EMPTY CELLS*/
Cells(Row_to_write, Columns_to_write) = Cells(Row_to_read,i).Address
'/*INCREMENT COUNTER WRITE*/
Columns_to_write = Columns_to_write + 1
End If
Next i
End Sub

Return text when looking up data

I have a spreadsheet which looks like this:
Name Task Date
Mike Go to the beach 10/1/13
Mike Go Shopping 10/2/13
Mike Go to work 10/3/13
Bill Go Hiking 10/1/13
Bill Go to work 10/3/13
I am trying to build another tab to the spreadsheet which will look at the data tab and return the matching text value when the rows and the columns match.
I'm trying to use a formula create a type of pivot table.
The results should look like this:
Name 10/1/13 10/2/13 10/3/13
Mike Go to the beach Go shopping Go to work
Bill Go Hiking *Blank* Go to work
I tried to post images but couldn't since this is my first post.
I hope you can understand what I am asking.
I am no expert in Pivot Tables, I have done it the dumb way - but works. Assumptions:
1) Source Data always on "Sheet1" with those 3 column headers
2) The "Sheet2" will be used to store sorted data
Sub SO_19105503()
Const NameCol As Long = 1
Const TaskCol As Long = 2
Const DateCol As Long = 3
Dim oShSrc As Worksheet, oShTgt As Worksheet, R As Long, C As Long
Dim aNames As Variant, aDates As Variant
Dim lNames As Long, lDates As Long
Dim oRng As Range, oArea As Range
Set oShSrc = ThisWorkbook.Worksheets("Sheet1") ' Source worksheet with original data
oShSrc.Copy Before:=oShSrc
Set oShSrc = ThisWorkbook.Worksheets("Sheet1 (2)") ' Copy of Source worksheet
Set oShTgt = ThisWorkbook.Worksheets("Sheet2") ' Target worksheet to store sorted data
oShSrc.AutoFilterMode = False
' Get unique names (sorted) in column A
aNames = Array()
lNames = 0
R = 1
oShSrc.UsedRange.Sort Key1:=oShSrc.Cells(R, NameCol), Header:=xlYes
Do
R = R + 1
If Not IsEmpty(oShSrc.Cells(R, NameCol)) And oShSrc.Cells(R, NameCol).Value <> oShSrc.Cells(R - 1, NameCol).Value Then
ReDim Preserve aNames(lNames)
aNames(lNames) = oShSrc.Cells(R, NameCol).Value
lNames = lNames + 1
End If
Loop Until IsEmpty(oShSrc.Cells(R, NameCol))
' Get unique dates (sorted) in column C
aDates = Array()
lDates = 0
R = 1
oShSrc.UsedRange.Sort Key1:=oShSrc.Cells(R, DateCol), Header:=xlYes
Do
R = R + 1
If Not IsEmpty(oShSrc.Cells(R, DateCol)) And oShSrc.Cells(R, DateCol).Value <> oShSrc.Cells(R - 1, DateCol).Value Then
ReDim Preserve aDates(lDates)
aDates(lDates) = oShSrc.Cells(R, DateCol).Value
lDates = lDates + 1
End If
Loop Until IsEmpty(oShSrc.Cells(R, DateCol))
' Prepare and put data to Target sheet
oShTgt.Range("A1").Value = oShSrc.Range("A1").Value ' Name
' Insert Dates (start from column B on Row 1)
For C = 0 To lDates - 1
oShTgt.Cells(1, C + 2).Value = aDates(C)
Next
' Insert Names (start from Row 2 on Column A)
For R = 0 To lNames - 1
oShTgt.Cells(R + 2, 1).Value = aNames(R)
Next
' Reprocess the source data with Autofilter
For R = 0 To lNames - 1
oShSrc.AutoFilterMode = False ' Remove AutoFilter before apply
' Apply AutoFilter with Criteria of R'th entry in array aNames
oShSrc.UsedRange.AutoFilter Field:=1, Criteria1:="=" & aNames(R)
' Go through Ranges in each Area
For Each oArea In oShSrc.Cells.SpecialCells(xlCellTypeVisible).Areas
For Each oRng In oArea.Rows
' Stop checking if row is more than used
If oRng.Row > oShSrc.UsedRange.Rows.count Then
Exit For
End If
' Check only if the row is below the header
If oRng.Row > 1 Then
For C = 0 To lDates - 1
' Find the matching date and put the "Task" value
If oShSrc.Cells(oRng.Row, DateCol).Value = aDates(C) Then
oShTgt.Cells(R + 2, C + 2).Value = oShSrc.Cells(oRng.Row, TaskCol).Value
Exit For
End If
Next C
End If
Next oRng
Next oArea
Next R
Application.DisplayAlerts = False
oShSrc.Delete ' Delete the temporary data source sheet
Application.DisplayAlerts = True
Set oShSrc = Nothing
Set oShTgt = Nothing
End Sub
Screenshots - Source Data/Result:

Excel macro - running through cells on the same level

So I want to run through A1-C200 and paste everything into a Word document. The trouble is, I have two ways of pasting it into Word, but each one has its downfall.
Goal: Copy A1-C200 into Word and keep the column layout, without copying blancs.
Example 1:
The code below copies everything into Word, but runs from A1 -> A200, B1 -> B200, C1 -> C200. Because it reads through my file this way, I lose my column layout. I would prefer a solution for this example, because this code looks clearer to me.
iMaxRow = 200
" Loop through columns and rows"
For iCol = 1 To 3
For iRow = 1 To iMaxRow
With Worksheets("GreatIdea").Cells(iRow, iCol)
" Check that cell is not empty."
If .Value = "" Then
"Nothing in this cell."
"Do nothing."
Else
" Copy the cell to the destination"
.Copy
appWD.Selection.PasteSpecial
End If
End With
Next iRow
Next iCol
Example 2:
The code below copies the correct column layout, but also inserts blancs. So if A1-A5 and A80-A90 are filled in, I will have 75 blancs in my Word document.
a1 = Range("A1").End(xlDown).Address
lastcell = Range("C1").Address
Range(a1, lastcell).Copy
With Range("A1")
Range(.Cells(1, 1), .End(xlDown).Cells(2, 3)).Copy
End With
Range("A1:C50").Copy
appWD.Selection.PasteSpecial
There's multiple ways to do this, don't know which is the quickest but here's some code I threw together real quick for you. Getting the range all at once in a variant is the fastest way to grab data out of excel.
Sub test()
Dim i As Long, j As Long
Dim wd As Word.Document
Dim wdTable As Word.Table
Dim wks As Excel.Worksheet
Dim v1 As Variant
Set wd = GetObject("C:\Documents and Settings\Jon\Desktop\New Microsoft Word Document.doc")
'Get data in array
Set wks = ActiveSheet
v1 = wks.UsedRange
'Create table
Set wdTable = wd.Tables.Add(Range:=wd.Application.Selection.Range, NumRows:=1, NumColumns:= _
ubound(v1,2), DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
wdAutoFitFixed)
'Place data
For i = 1 To UBound(v1)
For j = 1 To UBound(v1, 2)
If Len(v1(i, j)) > 0 Then
'Add row if not enough rows, this can be done before the j loop if
'you know the first column is always filled.
'You can also do an advanced filter in excel if you know that the first
'column is filled always and filter for filled cells then just
'do a straight copy and paste using r1.specialcells(xlCellTypeVisible).copy
'If you know the rows ahead of time when you create the table you can create all the rows at once,
'which should save time.
wd.application.selection
If wdTable.Rows.Count < i Then wdTable.Rows.Add
wdTable.Cell(i, j).Range.Text = v1(i, j)
End If
Next j
Next i
Set wks = Nothing: Set wd = Nothing: Set v1 = Nothing
End Sub
not quite sure I understand the prob ... but here's a stab at it:
dim rg200x3 as range: set rg200x3 = range("a1:c200")
dim Col1 as new collection
dim Col2 as new collection
dim Col3 as new collection
dim rgRow as new range
dim sText as string
for each rgRow in rg200x3
sText = trim(rgRow.cells(1,1)): if (sText <> "") call Col1.Add(sText)
sText = trim(rgRow.cells(1,2)): if (sText <> "") call Col2.Add(sText)
sText = trim(rgRow.cells(1,3)): if (sText <> "") call Col3.Add(sText)
next rgRow
at this point Col1, Col2, and Col3 contain your text w the blank cells factored out, so now loop over these to print out
dim i as long
for i = 1 to 200
on error resume next ' (cheap way to avoid checking if index > collection sz)
debug.print Col1(i) + " | " Col2(i) + " | " + Col3(i)
on error goto 0
next i
(note: code typed in freehand with no checking ... )
How about this to sub for your first solution:
iMaxRow = 200
" Loop through columns and rows"
For iRow = 1 To iMaxRow
For iCol = 1 To 3
With Worksheets("GreatIdea").Cells(iRow, iCol)
" Check that cell is not empty."
If .Value = "" Then
"Nothing in this cell."
"Do nothing."
Else
"Copy the cell to the destination"
.Copy appWD.Selection.PasteSpecial
End If
End With
Next iCol
Next iRow

Resources