How to shift cells one place in a table in Microsoft Word 2013 after removing/inserting?

5,248

A few days ago I needed something like the one knezmilos asked for, and I din't find anything to do it. So, I created a VBA macro (Word 2016) to do just that. The macro works in four different ways:

  1. Shift all the cells to the right until the end of the table (Public Sub MoveCellsRight)
  2. Shift all the cells to the right until the first blank cell (Public Sub MoveCellsRightFirstBlankCell)
  3. Shift all the cells to the left until the beginning of the table (Public Sub MoveCellsLeft)
  4. Shift all the cells to the left until the first blank cell (Public Sub MoveCellsLeftFirstBlankCell)

This macro WILL NOT:

  1. Work with tables inside a cell.
  2. Work with splitted cells (Every row must have the same number of columns).
  3. Preserve the format of the cell. (I hope someone will improve this macro by adding this feature).

Here is the macro:


Option Explicit

Dim vmCurrentTableIndex As Integer
Dim vmCurrentTableRowCount As Integer
Dim vmCurrentTableColCount As Integer
Dim vmCurrentCellRow As Integer
Dim vmCurrentCellCol As Integer
Dim vmDirection As String
Enum StopCellMode
    FirstLastCell = 0
    FirstBlankCell = 1
End Enum

Public Sub MoveCellsRight()
    If SetModuleVariables("right") Then
        If CheckCurrentCellPosition() Then
            MoveCellContent (FirstLastCell)
        End If
    End If
End Sub

Public Sub MoveCellsLeft()
    If SetModuleVariables("left") Then
        If CheckCurrentCellPosition() Then
            MoveCellContent (FirstLastCell)
        End If
    End If
End Sub

Public Sub MoveCellsRightFirstBlankCell()
    If SetModuleVariables("right") Then
        If CheckCurrentCellPosition() Then
            MoveCellContent (FirstBlankCell)
        End If
    End If
End Sub

Public Sub MoveCellsLeftFirstBlankCell()
    If SetModuleVariables("left") Then
        If CheckCurrentCellPosition() Then
            MoveCellContent (FirstBlankCell)
        End If
    End If
End Sub

Private Function SetModuleVariables(vpDirection As String) As Boolean
    Dim vsOK As Boolean
    Dim vsMsgBoxValue As Integer
    'Check if the [cursor | insertion point] is inside a table.
    If ActiveDocument.ActiveWindow.Selection.Information(wdWithInTable) Then
        vsOK = True
        'Get the index of the current table. / Source: https://wordmvp.com/FAQs/MacrosVBA/GetIndexNoOfPara.htm
        vmCurrentTableIndex = ActiveDocument.Range(0, Selection.Tables(1).Range.End).Tables.Count
        vmCurrentTableRowCount = ActiveDocument.Tables(vmCurrentTableIndex).Rows.Count
        vmCurrentTableColCount = ActiveDocument.Tables(vmCurrentTableIndex).Columns.Count
        vmCurrentCellRow = ActiveDocument.ActiveWindow.Selection.Cells(1).RowIndex
        vmCurrentCellCol = ActiveDocument.ActiveWindow.Selection.Cells(1).ColumnIndex
        vmDirection = vpDirection
    Else
        vsMsgBoxValue = MsgBox("This command can be executed only within a table.", vbInformation, "Error")
        vsOK = False
    End If
    SetModuleVariables = vsOK
End Function

Private Function CheckCurrentCellPosition() As Boolean
    Dim vsOK As Boolean
    Dim vsMsgBoxValue As Integer
    vsOK = True
    If vmDirection = "right" Then
        If vmCurrentCellRow = vmCurrentTableRowCount And vmCurrentCellCol = vmCurrentTableColCount Then
            vsMsgBoxValue = MsgBox("This is the last cell. There is no cell to move to the right.", vbCritical, "Error")
            vsOK = False
        End If
    Else
        If vmCurrentCellRow = 1 And vmCurrentCellCol = 1 Then
            vsMsgBoxValue = MsgBox("This is the first cell. There is no cell to move to the left.", vbCritical, "Error")
             vsOK = False
        End If
    End If
    CheckCurrentCellPosition = vsOK
End Function

Private Sub MoveCellContent(vpStopCellMode As StopCellMode)
    Dim vsCol As Integer
    Dim vsRow As Integer
    Dim vsStartRow As Integer
    Dim vsStartCol As Integer
    Dim vsEndRow As Integer
    Dim vsEndCol As Integer
    Dim vsStep As Integer
    Dim IsStartColSet As Boolean
    Dim vsCurrentCellContent As String
    Dim vsPreviousCellContent As String
    Dim vsLenght As Integer
    vsPreviousCellContent = ""
    IsStartColSet = False
    vsStartRow = vmCurrentCellRow
    vsStartCol = vmCurrentCellCol
    If vmDirection = "right" Then
        vsStep = 1
        vsEndRow = vmCurrentTableRowCount
        vsEndCol = vmCurrentTableColCount
    Else
        vsStep = -1
        vsEndRow = 1
        vsEndCol = 1
    End If
    For vsRow = vsStartRow To vsEndRow Step vsStep
        For vsCol = vsStartCol To vsEndCol Step vsStep
            vsLenght = Len(ActiveDocument.Tables(vmCurrentTableIndex).Cell(vsRow, vsCol).Range.Text) - 2
            vsCurrentCellContent = Left(ActiveDocument.Tables(vmCurrentTableIndex).Cell(vsRow, vsCol).Range.Text, vsLenght)
            ActiveDocument.Tables(vmCurrentTableIndex).Cell(vsRow, vsCol).Range.Text = vsPreviousCellContent
            vsPreviousCellContent = vsCurrentCellContent
            If vsCurrentCellContent = "" And vpStopCellMode = FirstBlankCell Then
                Exit Sub
            End If
        Next
        If IsStartColSet = False Then
            If vmDirection = "right" Then
                vsStartCol = 1
            Else
                vsStartCol = vmCurrentTableColCount
            End If
            IsStartColSet = True
        End If
    Next
End Sub
Share:
5,248

Related videos on Youtube

knezmilos
Author by

knezmilos

Updated on September 18, 2022

Comments

  • knezmilos
    knezmilos over 1 year

    If I have a table like this:

    A B
    C D
    E F
    

    When I remove cell B, I want all cells to shift one place towards A like this:

    A C
    D E
    F
    

    How to achieve this? Also, how to get the opposite - to insert a single cell somewhere and have all other cells move one place?

    • Hannu
      Hannu about 6 years
      Images can be made align like this, if they're small enough to fit between margins. Now I have no Word to play with, so: Can separate small tables be med behave in the same manner?
    • Hannu
      Hannu about 6 years
      As you're a reputation 1 user: If an answer helped you, don't forget to click the grey ☑ to the left of the text, which means "yes, this is THE answer"!
    • knezmilos
      knezmilos about 6 years
      It would probably work with small tables, but the problem is that I already have a huge table that I'm editing. And it would probably behave a bit different like that.
    • LPChip
      LPChip about 6 years
      This would not be possible with a full table structure that word uses. It could only work if each cell is its own table with a fixed size and make word wrap it around. Given that you already have a huge table, Its fair to say that it will be as much work to convert the table structure as to remake it which means: no, its not possible. A VBA macro would be far to complicated to make this work.
    • LPChip
      LPChip about 6 years
      Also note, Word is not really the tool for this. Publisher is far better suited for stuff like this. Publisher is like word, except arranging sections of words is its power, where in word, its its weakness. You may actually have better luck if you can copy everything to publisher and try to perform the action there.
  • LPChip
    LPChip about 6 years
    -1 because there is no VBA macro in this answer. And there won't be one because from experience I can tell you its virtually impossible to do this. VBA Macro's in word can't identify a table that easily, so in a huge document its going to be really hard to do this.
  • Hannu
    Hannu about 6 years
    I would wager though that it is possible, using relative cursor movements and selection created by keyboard input (hold down SHIFT while moving the cursor). No means to try currently
  • LPChip
    LPChip about 6 years
    Everything is possible, but the skill level to accomplish this is far beyond a casual user. You would need to know the document inside out and VBA too. OP certainly can't do that, and due to the same problem that you don't have the document, good luck getting some code that they can use without any modification necessary. Did I mention counteracting the way Word works with cells when suddenly they wrap around pages, etc... making the cursor move to unwanted locations etc.
  • Hannu
    Hannu about 6 years
    VBA: Not necessarily, "Record Macro" might be all that is needed. Last sentence: Agreed.
  • LPChip
    LPChip about 6 years
    Yeah... I highly doubt you can record a macro, record some keypresses and get a huge table shift their cells around exactly the way OP wants. Not to mention that if you need to repeat the macro so many times, it may be quicker to do by hand anyway, without recording the macro.
  • Hannu
    Hannu about 6 years
    Well, as I have not tried exactly the above, I cannot say for sure how well it would work / if it does work. But why give up before you even try? And last: I'd rather have the macro run for hours than do the same by hand.
  • LPChip
    LPChip about 6 years
    The macro won't run for hours. Making it will costs hours though. What do you do if you have a cell that is say... 100 px wide and has one sentence in it? Then the next one has 5 sentences in it? And the next has 9 in it? You can't just shift-down and hope you get to the end of the cell. There's no command to go to the end of the cell either, so excel will warp to the next cell. I am not giving up, I am seeing a challenge that is way harder than this answer suggests, which is why I downvoted it.
  • Hannu
    Hannu about 6 years
    updated text above. The "hours" you suggest it would take may well be a good investment in finding new ways of thinking.