Delete empty rows in comment in Excel using VBA - vba

I'm looking for a way to delete empty rows in comments using VBA. I have an Excel file with loads of corrupted comments, containing empty rows, and going through them one by one is not an option.
I haven't identified a command for editing rows in comments, and don't know where to start, so I don't have any code to show you guys. But I'm thinking in the line of:
For Each comment In ActiveSheet.Comments
"REMOVE EMPTY ROWS" <-- What to put here?
Next comment
Hope that you can help me anyway!
EDIT:
All my empty lines are at the end of the comment like this:

I found the answer. It seems that it's not empty rows, it's just the size of the comment that was changed somehow. So this code fixed it:
Sub Comments_AutoSize()
Dim MyComments As Comment
Dim lArea As Long
For Each MyComments In ActiveSheet.Comments
With MyComments
.Shape.TextFrame.AutoSize = True
If .Shape.Width > 300 Then
lArea = .Shape.Width * .Shape.Height
.Shape.Width = 200
.Shape.Height = (lArea / 200) * 1.1
End If
End With
Next
End Sub

Suppose your comment looks like this
You could try this
Sub RemoveEmptyLinesInComments()
Dim c As Comment
For Each c In ActiveSheet.Comments
c.Text Text:=Replace(c.Text, vbLf, Chr(32))
Next c
End Sub
to achieve
Update
Ok, after you've edited your question and changed the meaning with the provided details Ive come up with another code as a solution. Try
Sub RemoveEmptiesFromComments()
Dim c As Comment
For Each c In ActiveSheet.Comments
Dim v As Variant
v = Split(c.Text, Chr(32))
Dim i As Long, s As String
For i = LBound(v) To UBound(v) - 1
s = s & Chr(32) & v(i)
Next i
Dim rng As Range
Set rng = c.Parent
c.Delete
rng.AddComment Text:=s
rng.Comment.Shape.TextFrame.AutoSize = True
Next c
End Sub

Related

Concatenated string is not recognized by my Sub

I made the following Sub to help me copy values from other workbooks or even just from other sheets within the same workbook.
Private Sub CopyValues(fromSheet As String, fromRange As String, toSheet As String, toRange As String, Optional fromFileName As String = "")
Dim toFile As Excel.Workbook
Set toFile = ActiveWorkbook
Dim fromFile As Excel.Workbook
If Len(fromFileName) > 0 Then
Set fromFile = Workbooks.Open(fromFileName)
Else
Set fromFile = ActiveWorkbook
End If
With ActiveWorkbook
toFile.Sheets(toSheet).Range(toRange).Value = fromFile.Sheets(fromSheet).Range(fromRange).Value
End With
If Len(fromFileName) > 0 Then
fromFile.Close savechanges:=False
End If
End Sub
It works pretty well (and you all are free to use it if you find it helpful). Below is an example of code that works:
Call CopyValues(reportName, "B4:C15", reportName, "E2:F13", reportDirPath)
Unfortunately, I'm having trouble with a specific case. I'm looking to copy the same value into multiple cells in the same column. Below is what I came up with:
For i = 2 To i = 13
Call CopyValues(reportName, "AJ2", reportName, "H" + i, reportDirPath)
Next i
That didn't work. No error messages, but none of the values were pasted into my sheet. I thought that maybe concatenating the integer i was converting (is that the technical word?) the string to a different type, so I tried the following:
For i = 2 To i = 13
Call CopyValues(reportName, "AJ2", reportName, CStr("H" + i), reportDirPath)
Next i
That still didn't work. Same deal. No error messages, but none of the values were pasted into my sheet.
Changing the + to an & also didn't work:
For i = 2 To i = 13
Call CopyValues(reportName, "AJ2", reportName, CStr("H" & i), reportDirPath)
Next i
Obviously, I could just write out each individual case, but that seems kind of ridiculous. Any idea what's going on?
When I tried your code your 'For' loops were not working, but after I changed your for loop to say 'For i = 2 to 13' as opposed to 'For i=2 To i = 13' the last version of your code worked for me.
For i = 2 To 13
Call CopyValues("Sheet1", "A1", "Sheet2", CStr("J" & i))
Next i
End Sub
So I think that could have been your trouble.

VBA Sub to Remove Blanks From Row Improvements

I wrote a sub to remove the blank entries in a row without shifting the cells around but it seems unnecessarily clunky and I'd like to get some advice on how to improve it.
Public Sub removeBlankEntriesFromRow(inputRow As Range, pasteLocation As String)
'Removes blank entries from inputRow and pastes the result into a row starting at cell pasteLocation
Dim oldArray, newArray, tempArray
Dim j As Integer
Dim i As Integer
'dump range into temp array
tempArray = inputRow.Value
'redim the 1d array
ReDim oldArray(1 To UBound(tempArray, 2))
'convert from 2d to 1d
For i = 1 To UBound(oldArray, 1)
oldArray(i) = tempArray(1, i)
Next
'redim the newArray
ReDim newArray(LBound(oldArray) To UBound(oldArray))
'for each not blank in oldarray, fill into newArray
For i = LBound(oldArray) To UBound(oldArray)
If oldArray(i) <> "" Then
j = j + 1
newArray(j) = oldArray(i)
End If
Next
'Catch Error
If j <> 0 Then
'redim the newarray to the correct size.
ReDim Preserve newArray(LBound(oldArray) To j)
'clear the old row
inputRow.ClearContents
'paste the array into a row starting at pasteLocation
Range(pasteLocation).Resize(1, j - LBound(newArray) + 1) = (newArray)
End If
End Sub
Here is my take on the task you describe:
Option Explicit
Option Base 0
Public Sub removeBlankEntriesFromRow(inputRow As Range, pasteLocation As String)
'Removes blank entries from inputRow and pastes the result into a row starting at cell pasteLocation
Dim c As Range
Dim i As Long
Dim new_array As String(inputRow.Cells.Count - WorksheetFunction.CountBlank(inputRow))
For Each c In inputRow
If c.Value <> vbNullString Then
inputRow(i) = c.Value
i = i + 1
End If
Next
Range(pasteLocation).Resize(1, i - 1) = (new_array)
End Sub
You'll notice that it is quite different, and while it may be slightly slower than your solution, because it is using a for each-loop instead of looping through an array, if my reading of this answer is correct, it shouldn't matter all that much unless the input-range is very large.
It is significantly shorter, as you see, and I find it easier to read - that may just be familiarity with this syntax as opposed to yours though. Unfortunately I'm not on my work-computer atm. to test it out, but I think it should do what you want.
If your main objective is to improve the performance of the code, I think that looking into what settings you may turn off while the code is running will have more effect than exactly what kind of loop and variable assignment you use. I have found this blog to be a good introduction to some concepts to bear in mind while coding in VBA.
I hope you have found my take on your problem an interesting comparison to your own solution, which as others have mentioned should work just fine!
If I am to understand you want to delete blanks and pull the data left on any given row?
I would do it by converting the array to a string joined with pipe |, clean any double pipes out (loop this until there are no doubles left) then push it back to an array across the row:
Here is my code:
Sub TestRemoveBlanks()
Call RemoveBlanks(Range("A1"))
End Sub
Sub RemoveBlanks(Target As Range)
Dim MyString As String
MyString = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(Range(Target.Row & ":" & Target.Row))), "|")
Do Until Len(MyString) = Len(Clean(MyString))
MyString = Clean(MyString)
Loop
Rows(Target.Row).ClearContents
Target.Resize(1, Len(MyString) - Len(Replace(MyString, "|", ""))).Formula = Split(MyString, "|")
End Sub
Function Clean(MyStr As String)
Clean = Replace(MyStr, "||", "|")
End Function
I put a sub to test in there for you.
If you have pipes in your data, substitute it with something else in my code.

Adding comments to MS Word tables

I'm trying to add comments to the table rows. the idea is that you select a table and the macro would add a comment to every row.
say you have a string followed by an integer in the comment content.
example comment content would be :
comment1
comment2
comment3
Note that the contents of the comments are important , as they play a vital role.
Here is what I got so far , if some one has already got this figured out , please help me out
Sub CallAddNewComment()
Dim i As Integer
i = ActiveDocument.Tables(1).Rows.Count
Do Until (i > 1)
Call AddNewComment(strText:="This is a test comment.")
Loop
End Sub
Sub AddNewComment(ByVal strText As String)
Comments.Add Row = i, Text:=strText
End Sub
Sub Tester()
Dim tbl As Table, i As Long
For Each tbl In ActiveDocument.Tables
For i = 1 To tbl.Rows.Count
ActiveDocument.Comments.Add _
tbl.Rows(i).Cells(1).Range, "Comment" & i
Next i
Next tbl
End Sub

VBA code to hide a number of fixed discrete rows across a few worksheets

I'm for a solution to part of a macro I'm writing that will hide certain (fixed position) rows across a few different sheets. I currently have:
Sheets(Sheet1).Range("5:20").EntireRow.Hidden = True
To hide rows 5-20 in Sheet1. I also would like to hide (for arguements sake), row 6, row 21, and rows 35-38 in Sheet2 - I could do this by repeating the above line of code 3 more times; but am sure there's a better way of doing this, just as a learning exercise.
Any help much appreciated :)
Chris
Specify a Union of some ranges as follows
With Sheet1
Union(.Range("1:5"), .Rows(7), .Range("A10"), .Cells(12, 1)).EntireRow.Hidden = True
End With
Here is a try:
Sub hideMultiple()
Dim r As Range
Set r = Union(Range("A1"), Range("A3"))
r.EntireRow.Hidden = True
End Sub
But you cannot Union range from several worksheets, so you would have to loop over each worksheet argument.
This is a crude solution: no validation, no unhiding of existing hidden rows, no check that I have a sheet name as first parameter, etc. But it demonstrates a technique that I often find useful.
I load an array with a string of parameters relevant to my current problem and code a simple loop to implement them. Look up the sub and function declarations and read the section on ParamArrays for a variation on this approach.
Option Explicit
Sub HideColumns()
Dim InxPL As Integer
Dim ParamCrnt As String
Dim ParamList() As Variant
Dim SheetNameCrnt As String
ParamList = Array("Sheet1", 1, "5:6", "Sheet2", 9, "27:35")
SheetNameCrnt = ""
For InxPL = LBound(ParamList) To UBound(ParamList)
ParamCrnt = ParamList(InxPL)
If InStr(ParamCrnt, ":") <> 0 Then
' Row range
Sheets(SheetNameCrnt).Range(ParamCrnt).EntireRow.Hidden = True
ElseIf IsNumeric(ParamCrnt) Then
' Single Row
Sheets(SheetNameCrnt).Range(ParamCrnt & ":" & _
ParamCrnt).EntireRow.Hidden = True
Else
' Assume Sheet name
SheetNameCrnt = ParamCrnt
End If
Next
End Sub

VB.NET excel deleting multiple columns at the same time

I am trying to delete more than one column in my excel sheet.
For Each lvi In ListView1.Items
If lvi.Checked = True Then
arrayLetters = lvi.SubItems(1).Text & ":" & lvi.SubItems(1).Text & "," & arrayLetters
End If
Next
arrayLetters = arrayLetters.Substring(0, arrayLetters.Length - 1)
Dim rg As Excel.Range = xlSheet.Columns(arrayLetters)
rg.Select()
rg.Delete()
The value of arrayLetters is "G:G,F:F". For some reason that doesn't seem to work once it gets there to delete them! Only reason i am doing it this way is so that it doesn't update the table and loop to the other one. In other words, if i delete each one individually then the column moves and the letter will not be the same the next go around.
The error is on the Dim rg As Excel.Range = xlSheet.Columns(arrayLetters) line and it says:
Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH))
Any help would be great!
David
SOLVED
For Each lvi In ListView1.Items
If lvi.Checked = False Then
arrayLetters = lvi.SubItems(2).Text & "," & arrayLetters 'Puts numbers in BACKWORDS
End If
Next
arrayLetters = arrayLetters.Substring(0, arrayLetters.Length - 1)
Dim theNumbers As String() = arrayLetters.Split(",")
Dim num As Integer = 0
xlApp.ScreenUpdating = False
For Each num In theNumbers
xlSheet.Columns(num).delete() 'Deletes columns in reverse order (7,5,4...)
Next
Just delete the lowest numbered column N number of times to reflect how many columns in a row you want to delete. It's better to go off of column numbers rather than letters when dealing with Excel programatically. If you need a code example, let me know and I'll post one.
Edit:
Here is a code example that does what you want:
xlSheet.Columns(i).delete
You want
xlSheet.Range(arrayLetters)
I reckon, that is Range, not Column.
I think the important part to realize (which I didn't initially) is that you have to use numbers for the columns not the letters.