У меня есть код для выбора указанного диапазона и вставки его в электронное письмо. Я хотел бы пропустить копирование пустых ячеек и вставить только те ячейки, которые содержат данные.
Диапазон должен оставаться прежним, поскольку это таблица, заполненная из внешних источников. Иногда ячейки могут быть пустыми, а иногда пустыми будут разные ячейки. Иногда ни одна ячейка не будет пуста.
Я пробовал константы. Тогда будет вставлен только диапазон C13:J13. Это единственная строка, в ячейках которой нет формул, только текст. Все остальные ячейки в диапазоне содержат формулы. Я думаю, было бы лучше проверить, <1 ли длина, а затем пропустить.
Sub PrepareMailOffer()
Dim rng As Range
Dim OutApp As Object
Dim OutMail As Object
Set rng = Nothing
On Error Resume Next
Set rng = Sheets("000000").Range("C12:J29").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If rng Is Nothing Then
MsgBox "The selection is not a range or the sheet is protected" & _
vbNewLine & "please correct and try again.", vbOKOnly
Exit Sub
End If
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = Range("N4").Value
.CC = ""
.BCC = ""
.Subject = ""
.HTMLBody = "" & _
RangetoHTML(rng) & _
"" & _
.Display
End With
On Error GoTo 0
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Function RangetoHTML(rng As Range)
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "\" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to paste the data in
rng.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML = ts.readall
ts.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource = ", _
"align=left x:publishsource = ")
'Close TempWB
TempWB.Close savechanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function
Код работает, когда у меня нет пустых ячеек.
В моем первоначальном проекте предполагалась фильтрация, но вместо этого я решил использовать формулы. Я не обновлял код, чтобы отразить это изменение. Нет скрытых строк, есть целые пустые строки. Я хочу, чтобы код выбирал и вставлял только строки с данными и пропускал пустые строки.
Я забыл упомянуть, что «пустые строки» содержат формулы, поэтому технически они не пустые. Вот почему я думаю, что проверка длины будет лучшим решением, чем SkipBlanks, который не работает.
Итак, вы не хотите пропускать пустые ячейки, что выглядело бы странно, остальные столбцы/строки должны скользить в одном направлении. Затем есть пустые строки, а также результаты формул. Это означает, что xlCellTypeVisible бесполезен, и вы также не можете использовать xlCellTypeConstants для получения прерывистого диапазона, пропуская пустые строки. Но функция рабочего листа CountBlank должна работать, и вы можете скрыть пустые строки, а затем использовать xlCellTypeVisible. Вы копируете диапазон **вручную? Вам нужно снова сделать скрытую строку видимой после копирования диапазона?
Вероятно, вам нужно показать остальную часть кода, чтобы увидеть, как вы копируете диапазон...
Я отредактировал свой вопрос, включив полный код


Sub ReferenceNonBlankRows()
' Define constants.
Const SHEET_NAME As String = "000000"
Const RANGE_ADDRESS As String = "C12:J29"
' Reference the main objects.
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets(SHEET_NAME)
Dim rg As Range: Set rg = ws.Range(RANGE_ADDRESS)
' Store the range's number of columns in a variable ('ColumnsCount').
Dim ColumnsCount As Long: ColumnsCount = rg.Columns.Count
' Declare additional variables.
Dim urg As Range, rrg As Range, IsFoundNonBlankRow As Boolean
' Loop through the rows ('rrg') of the range ('rg')
' and combine each non-blank row ('rrg') into a unioned range ('urg').
For Each rrg In rg.Rows
' 'CountBlank' counts the number of blank cells
' (cells whose length is 0) in a range.
If Application.CountBlank(rrg) < ColumnsCount Then
If IsFoundNonBlankRow Then
Set urg = Union(urg, rrg)
Else
Set urg = rrg
IsFoundNonBlankRow = True ' never reset
End If
End If
Next rrg
' Check if all rows are blank.
If Not IsFoundNonBlankRow Then
MsgBox "All rows in the range ""'" & ws.Name & "'!" _
& rg.Address(0, 0) & """ are blank!", vbExclamation
Exit Sub
End If
' Continue using 'urg', e.g.:
MsgBox "The rows ""'" & ws.Name & "'!" _
& urg.Address(0, 0) & """ are not blank.", vbInformation
End Sub
Function RefNonBlankRows( _
ByVal rg As Range, _
Optional ByVal ShowFailMessage As Boolean = False) _
As Range
' Store the range's number of columns in a variable ('ColumnsCount').
Dim ColumnsCount As Long: ColumnsCount = rg.Columns.Count
' Declare additional variables.
Dim urg As Range, rrg As Range, IsFoundNonBlankRow As Boolean
' Loop through the rows ('rrg') of the range ('rg')
' and combine each non-blank row ('rrg') into a unioned range ('urg').
For Each rrg In rg.Rows
' 'CountBlank' counts the number of blank cells
' (cells whose length is 0) in a range.
If Application.CountBlank(rrg) < ColumnsCount Then
If IsFoundNonBlankRow Then
Set urg = Union(urg, rrg)
Else
Set urg = rrg
IsFoundNonBlankRow = True ' never reset
End If
End If
Next rrg
' Check if all rows are blank.
If Not IsFoundNonBlankRow Then
If ShowFailMessage Then
MsgBox "All rows in the range ""'" & rg.Worksheet.Name & "'!" _
& rg.Address(0, 0) & """ are blank!", vbExclamation
End If
Exit Function
End If
' Assign non-blank rows to the result of the function.
Set RefNonBlankRows = urg
End Function
Sub PrepareMailOffer()
' Define constants.
Const SHEET_NAME As String = "000000"
Const RANGE_ADDRESS As String = "C12:J29"
Const EMAIL_CELL_ADDRESS As String = "N4"
' Reference the main objects.
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets(SHEET_NAME)
Dim rg As Range: Set rg = ws.Range(RANGE_ADDRESS)
' Reference the non-blank rows.
Dim nbrg As Range: Set nbrg = RefNonBlankRows(rg, True)
If nbrg Is Nothing Then Exit Sub
Dim outApp As Object: Set outApp = CreateObject("Outlook.Application")
Dim outMail As Object: Set outMail = OutApp.CreateItem(0)
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
On Error Resume Next
With outMail
.To = ws.Range(EMAIL_CELL_ADDRESS).Value
.CC = ""
.BCC = ""
.Subject = ""
.HTMLBody = "" _
& "" _
& RangetoHTML(nbrg) _
& ""
.Display
End With
On Error GoTo 0
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
Огромное спасибо за это - все работает так, как я и предполагал. Мне жаль, что я не могу также пометить ваш ответ «зеленым», но FaneDuru работает так же хорошо, и они были первыми, кто помог мне в моем небольшом проекте. Заботиться!
Пожалуйста, попробуйте следующий адаптированный код, который скрывает пустые строки (даже с пробелами в формуле) и обрабатывает видимые ячейки результирующего диапазона:
Sub PrepareMailOffer()
Dim ws As Worksheet, rng As Range, rngH As Range, i As Long
Dim OutApp As Object, OutMail As Object
Set ws = Sheets("000000")
Set rng = ws.Range("C12:J29")
'place the blank rows in a Union range and hide them, at once:
For i = 1 To rng.rows.count
If WorksheetFunction.CountBlank(rng.rows(i)) = rng.Columns.count Then
addToRange rngH, rng.rows(i).EntireRow
End If
Next i
If Not rngH Is Nothing Then rngH.EntireRow.Hidden = True 'hide the blank rows
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = Range("N4").Value
.cc = ""
.BCC = ""
.Subject = ""
.HTMLBody = "" & _
RangetoHTML(rng.SpecialCells(xlCellTypeVisible)) & _
"" & _
.Display
End With
If Not rngH Is Nothing Then rngH.EntireRow.Hidden = False 'unhide the previous hidden rows
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Sub addToRange(rngU As Range, rng As Range)
If rngU Is Nothing Then
Set rngU = rng
Else
Set rngU = Union(rngU, rng)
End If
End Sub
On Error Resume Next только в контексте вашего кода не сообщайте вам, какая у вас ошибка, если таковая имеется...
Вам следует использовать ту же (существующую) функцию RangetoHTML...
Пожалуйста, оставьте отзыв после тестирования.
Я отредактировал свой вопрос, включив полный код
Огромное спасибо за это - все работает так, как я хотел.
Отфильтрован ли диапазон, который вы пытаетесь обработать, для использования
xlCellTypeVisible? Я имею в виду, есть ли скрытые строки? И есть ли пустые ячейки или пустые строки? Если вы хотите пропустить пустые ячейки, как бы вы хотели, чтобы код вел себя в случае таких ячеек? Должны ли столбцы перемещаться вместо пустых ячеек? Вы понимаете, что я имею в виду? Я думаю, было бы хорошо поместить изображение с существующими (содержащими пустые ячейки) и изображение, показывающее, как выглядит обработанный диапазон...