Public Sub numbers() With ActiveSheet.UsedRange For Each oCell In .Range("A:A,C:K,N:O") If oCell <> "" And Val(oCell) <> 0 Then oCell.Formula = Val(oCell) End If Next End With End Sub
[/vba]
если в таблицу будут добавляться столбцы справа, которые нужно будет обработать, то можно вместо
[vba]
Код
For Each oCell In .Range("A:A,C:K,N:O")
[/vba] написать [vba]
Код
For Each oCell In .Range("A:A,C:K,N:" & _ Split(Columns(.Column + .Columns.Count - 1).Address(False, False), ":")(0))
[/vba]
чтобы ускорить работу макроса можно ограничить диапазон, указав количество обрабатываемых строк, но этот способ работает только с непрерывными диапазонами, из-за этого приходится добавлять еще один цикл [vba]
Код
Public Sub numbers() With ActiveSheet.UsedRange For Each Rng In Array("A:A", "C:K", "N:O") For Each ocell In .Range(Rng).Rows(.Row & ":" & .Row + .Rows.Count - 1).Cells If ocell <> "" And Val(ocell) <> 0 Then ocell.Formula = Val(ocell) End If Next Next End With End Sub
[/vba]
как-то так [vba]
Код
Public Sub numbers() With ActiveSheet.UsedRange For Each oCell In .Range("A:A,C:K,N:O") If oCell <> "" And Val(oCell) <> 0 Then oCell.Formula = Val(oCell) End If Next End With End Sub
[/vba]
если в таблицу будут добавляться столбцы справа, которые нужно будет обработать, то можно вместо
[vba]
Код
For Each oCell In .Range("A:A,C:K,N:O")
[/vba] написать [vba]
Код
For Each oCell In .Range("A:A,C:K,N:" & _ Split(Columns(.Column + .Columns.Count - 1).Address(False, False), ":")(0))
[/vba]
чтобы ускорить работу макроса можно ограничить диапазон, указав количество обрабатываемых строк, но этот способ работает только с непрерывными диапазонами, из-за этого приходится добавлять еще один цикл [vba]
Код
Public Sub numbers() With ActiveSheet.UsedRange For Each Rng In Array("A:A", "C:K", "N:O") For Each ocell In .Range(Rng).Rows(.Row & ":" & .Row + .Rows.Count - 1).Cells If ocell <> "" And Val(ocell) <> 0 Then ocell.Formula = Val(ocell) End If Next Next End With End Sub
Вообщем задача такая: ограничить движение курсора при нажатии левой кнопкой мыши на определенном диапазоне границами этого диапазона. Все, что я смог сделать- это написать код для правой кнопки мыши. В примере диапазоны, в которых должен "запираться" курсор выделены зеленым цветом. Все уперлось в хук. Нужно чтобы при нажатии левой кнопки движение курсора ограничивалось границами соответствующего диапазона и при отпускании левой кнопки ограничение снималось.
Вообщем задача такая: ограничить движение курсора при нажатии левой кнопкой мыши на определенном диапазоне границами этого диапазона. Все, что я смог сделать- это написать код для правой кнопки мыши. В примере диапазоны, в которых должен "запираться" курсор выделены зеленым цветом. Все уперлось в хук. Нужно чтобы при нажатии левой кнопки движение курсора ограничивалось границами соответствующего диапазона и при отпускании левой кнопки ограничение снималось.krosav4ig
function LowLevelMouseProc(Code: Integer; wParam: DWORD; lParam: DWORD): Longint; stdcall; begin if (Code = HC_ACTION) then begin if (wParam = WM_LBUTTONDOWN) then begin SendMessage(GlobalData.Wnd, MWM_LBUTTONDOWN, 0, 0); if Filters.BlockLeftButton = True then Result := - 1 else Result := CallNextHookEx(GlobalData^.WndHook, Code, wParam, lParam); end else if (wParam = WM_LBUTTONUP) then begin SendMessage(GlobalData.Wnd, MWM_LBUTTONUP, 0, 0); if Filters.BlockLeftButton = True then Result := - 1 else Result := CallNextHookEx(GlobalData^.WndHook, Code, wParam, lParam); end else Result := CallNextHookEx(GlobalData^.WndHook, Code, wParam, lParam); end; end;
function StartMouseHook(State: Boolean; Wnd: HWND): Boolean; export; stdcall; begin Result := False; if State = True then begin GlobalData^.WndHook := SetWindowsHookEx(WH_MOUSE_LL, @LowLevelMouseProc, hInstance, 0); GlobalData^.Wnd := Wnd; if GlobalData^.WndHook <> 0 then Result := True; end else begin UnhookWindowsHookEx(GlobalData^.WndHook); Result := False; end; end;
function StopMouseHook(): Boolean; export; stdcall; begin UnhookWindowsHookEx(GlobalData^.WndHook); if GlobalData^.WndHook = 0 then Result := False else Result := True; end;
function UpdateMouseHook(HookFilters: TMouseHookFilters): Boolean; export; stdcall; begin Filters := HookFilters; end;
if StartMouseHook(true, Handle) = true then HookEnable := true;
[/vba]
и обработчик нажатия [vba]
Код
procedure TForm1.WndProc(var Msg: TMessage) { отслеживаем нажатия левой кл. мыши } ; begin inherited; if (Msg.Msg = MWM_LBUTTONDOWN{MWM_LBUTTONUP}) then begin ShowMessage('DOWN'{'UP'}) end; end;
[/vba]
можно ли это как-нить прикрутить к VBA?
Нашел у себя в закромах библиотеку хука, написанную на delphi
[vba]
Код
library LowLevelMouseHook;
uses Windows, Messages;
const WH_MOUSE_LL = 14; MMFName: PChar = 'MMF';
type PGlobalDLLData = ^TGlobalDLLData; TGlobalDLLData = packed record WndHook: HWND; Wnd: HWND; end;
type TMouseHookFilters = record BlockMouseMove: boolean; BlockLeftButton: boolean; BlockRightButton: boolean; BlockMiddleButton: boolean; BlockWheel: boolean; end;
function LowLevelMouseProc(Code: Integer; wParam: DWORD; lParam: DWORD): Longint; stdcall; begin if (Code = HC_ACTION) then begin if (wParam = WM_LBUTTONDOWN) then begin SendMessage(GlobalData.Wnd, MWM_LBUTTONDOWN, 0, 0); if Filters.BlockLeftButton = True then Result := - 1 else Result := CallNextHookEx(GlobalData^.WndHook, Code, wParam, lParam); end else if (wParam = WM_LBUTTONUP) then begin SendMessage(GlobalData.Wnd, MWM_LBUTTONUP, 0, 0); if Filters.BlockLeftButton = True then Result := - 1 else Result := CallNextHookEx(GlobalData^.WndHook, Code, wParam, lParam); end else Result := CallNextHookEx(GlobalData^.WndHook, Code, wParam, lParam); end; end;
function StartMouseHook(State: Boolean; Wnd: HWND): Boolean; export; stdcall; begin Result := False; if State = True then begin GlobalData^.WndHook := SetWindowsHookEx(WH_MOUSE_LL, @LowLevelMouseProc, hInstance, 0); GlobalData^.Wnd := Wnd; if GlobalData^.WndHook <> 0 then Result := True; end else begin UnhookWindowsHookEx(GlobalData^.WndHook); Result := False; end; end;
function StopMouseHook(): Boolean; export; stdcall; begin UnhookWindowsHookEx(GlobalData^.WndHook); if GlobalData^.WndHook = 0 then Result := False else Result := True; end;
function UpdateMouseHook(HookFilters: TMouseHookFilters): Boolean; export; stdcall; begin Filters := HookFilters; end;
if StartMouseHook(true, Handle) = true then HookEnable := true;
[/vba]
и обработчик нажатия [vba]
Код
procedure TForm1.WndProc(var Msg: TMessage) { отслеживаем нажатия левой кл. мыши } ; begin inherited; if (Msg.Msg = MWM_LBUTTONDOWN{MWM_LBUTTONUP}) then begin ShowMessage('DOWN'{'UP'}) end; end;
В моем файле как раз это и реализовано. В макросе qwe() lek это количество часов лекций, lab это количество часов лабораторных, stud это количество студентов. При запуске этого макроса лист шаблон копируется и в скопированном листе таблицы подгоняются под заданные параметры. Запустить его можно с вкладки разработчик, посмотреть код макроса можно нажав alt+f11, все макросы в моем файле находятся в module1 в разделе modules. [p.s.]если на ленте нет вкладки разработчик, то как ее включить можно почитать тут
В моем файле как раз это и реализовано. В макросе qwe() lek это количество часов лекций, lab это количество часов лабораторных, stud это количество студентов. При запуске этого макроса лист шаблон копируется и в скопированном листе таблицы подгоняются под заданные параметры. Запустить его можно с вкладки разработчик, посмотреть код макроса можно нажав alt+f11, все макросы в моем файле находятся в module1 в разделе modules. [p.s.]если на ленте нет вкладки разработчик, то как ее включить можно почитать тутkrosav4ig
в процедуре Workbook_SheetChange я бы посоветовал заменить [vba]
Код
Select Case CStr(target) Case "_": MannagerList (-1) Case "Manager": MannagerList (1) Case "Manual_Worker", "Professional": MannagerList (0) End Select
[/vba] на [vba]
Код
If Not Intersect(target, Range("H4:I5")) Is Nothing Then Select Case CStr(target) Case "_": MannagerList (-1) Case "Manager": MannagerList (1) Case "Manual_Worker", "Professional": MannagerList (0) End Select End If
[/vba]
проблема №1 вариант с дополнительными столбцами
в ячейку M85 поставить два пробела в диапазоне N76:N85 формула
в процедуре Workbook_SheetChange я бы посоветовал заменить [vba]
Код
Select Case CStr(target) Case "_": MannagerList (-1) Case "Manager": MannagerList (1) Case "Manual_Worker", "Professional": MannagerList (0) End Select
[/vba] на [vba]
Код
If Not Intersect(target, Range("H4:I5")) Is Nothing Then Select Case CStr(target) Case "_": MannagerList (-1) Case "Manager": MannagerList (1) Case "Manual_Worker", "Professional": MannagerList (0) End Select End If
да и весь код процедуры MannagerList я бы переписал как-то так [vba]
Код
Sub MannagerList(Mang As Integer) Dim AA As Variant ActiveSheet.Unprotect AA = Array("Organization and planning", "Decision-making", _ "Team building, management And development", "Delegation and control", _ "Leadership and motivation", "Strategic thinking") ' "Manual_Worker", "Professional": If Mang = 0 Then Range("E39:E45").Value = " " ' Range("E46").Value = " " Range("B39").Value = "Professional Competencies" Range("D42:I44").RowHeight = 0 'Range("D44:I46").Select 'Range("D44:I46").Select ' Selection.RowHeight = 0 ' Уставновка With Range("E39:E44").Validation .Delete .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _ Operator:=xlBetween, Formula1:="=List" End With 'Установка в начало Range("E40").Select Range("D39").Value = 1 Range("D40").Value = 2 Range("D41").Value = 3 ElseIf Mang = 1 Then ' Manager For i = 0 To 5 Range("E" & 39 + i).Value = AA(i) Next 'Range("E46").Value = A7 Range("B39").Value = "Managerial Competencies" ' Высота строк Range("D40:I46").RowHeight = 14 ' Очистка данных проверки With Range("E39:E46").Validation .Delete .Add Type:=xlValidateInputOnly, AlertStyle:=xlValidAlertStop, _ Operator:=xlBetween End With ' Установка в текущее положение Range("E40").Select For i = 1 To 6 Range("D" & 38 + i).Value = i Next ElseIf Mang = -1 Then ' ************************************************************************* ' Пустое значение ' ************************************************************************* Range("B39").Value = "" Range("D39:D44").Value = "" Range("E39:E44").Value = "" End If ' Следующее поле для заполнения после выбора типа Range("C6").Select ActiveSheet.Protect End Sub
[/vba]
да и весь код процедуры MannagerList я бы переписал как-то так [vba]
Код
Sub MannagerList(Mang As Integer) Dim AA As Variant ActiveSheet.Unprotect AA = Array("Organization and planning", "Decision-making", _ "Team building, management And development", "Delegation and control", _ "Leadership and motivation", "Strategic thinking") ' "Manual_Worker", "Professional": If Mang = 0 Then Range("E39:E45").Value = " " ' Range("E46").Value = " " Range("B39").Value = "Professional Competencies" Range("D42:I44").RowHeight = 0 'Range("D44:I46").Select 'Range("D44:I46").Select ' Selection.RowHeight = 0 ' Уставновка With Range("E39:E44").Validation .Delete .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _ Operator:=xlBetween, Formula1:="=List" End With 'Установка в начало Range("E40").Select Range("D39").Value = 1 Range("D40").Value = 2 Range("D41").Value = 3 ElseIf Mang = 1 Then ' Manager For i = 0 To 5 Range("E" & 39 + i).Value = AA(i) Next 'Range("E46").Value = A7 Range("B39").Value = "Managerial Competencies" ' Высота строк Range("D40:I46").RowHeight = 14 ' Очистка данных проверки With Range("E39:E46").Validation .Delete .Add Type:=xlValidateInputOnly, AlertStyle:=xlValidAlertStop, _ Operator:=xlBetween End With ' Установка в текущее положение Range("E40").Select For i = 1 To 6 Range("D" & 38 + i).Value = i Next ElseIf Mang = -1 Then ' ************************************************************************* ' Пустое значение ' ************************************************************************* Range("B39").Value = "" Range("D39:D44").Value = "" Range("E39:E44").Value = "" End If ' Следующее поле для заполнения после выбора типа Range("C6").Select ActiveSheet.Protect End Sub
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) colors = Array(vbWhite, vbBlack, vbRed, vbGreen, vbYellow, vbBlue, vbMagenta, vbCyan, vbWhite) Cancel = True With Target.Interior For i = 0 To UBound(colors) If .Color = colors(i) Then .Color = colors(i + 1) Exit For ElseIf i = UBound(colors) Then .Color = colors(0) End If Next End With End Sub
[/vba]
и так
[vba]
Код
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) Words = Array("Рыба", "Кот", "Сметана", "Рыба") Cancel = True With Target For i = 0 To UBound(Words) If .Value = Words(i) Then .Value = Words(i + 1) Exit For ElseIf i = UBound(Words) Then .Value = Words(1) End If Next End With End Sub
[/vba]
а можно так?
[vba]
Код
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) colors = Array(vbWhite, vbBlack, vbRed, vbGreen, vbYellow, vbBlue, vbMagenta, vbCyan, vbWhite) Cancel = True With Target.Interior For i = 0 To UBound(colors) If .Color = colors(i) Then .Color = colors(i + 1) Exit For ElseIf i = UBound(colors) Then .Color = colors(0) End If Next End With End Sub
[/vba]
и так
[vba]
Код
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) Words = Array("Рыба", "Кот", "Сметана", "Рыба") Cancel = True With Target For i = 0 To UBound(Words) If .Value = Words(i) Then .Value = Words(i + 1) Exit For ElseIf i = UBound(Words) Then .Value = Words(1) End If Next End With End Sub
Alex_ST, о том самом Просто я исходя из уровня владения VBA топик-стартера решил все-таки написать пример реализации предложенного вами алгоритма, к тому же при использовании цикла в решении этой задачи есть пара нюансов, которые могут ввести в ступор новичка в программировании. В данном случае это невозможность использования обычного Else и необходимость выхода из цикла при срабатывании условия. Ну вот как-то так .
ant6729, я бы вам посоветовал для начала изучить синтаксис основных конструкций vba, типы данных и объектную модель excel (с общими сведениями объектной модели можно ознакомится по ссылке), на форуме есть раздел, где можно скачать справочники по excel и vba.
Alex_ST, о том самом Просто я исходя из уровня владения VBA топик-стартера решил все-таки написать пример реализации предложенного вами алгоритма, к тому же при использовании цикла в решении этой задачи есть пара нюансов, которые могут ввести в ступор новичка в программировании. В данном случае это невозможность использования обычного Else и необходимость выхода из цикла при срабатывании условия. Ну вот как-то так .
ant6729, я бы вам посоветовал для начала изучить синтаксис основных конструкций vba, типы данных и объектную модель excel (с общими сведениями объектной модели можно ознакомится по ссылке), на форуме есть раздел, где можно скачать справочники по excel и vba.krosav4ig
Написанные мной формулы - формулы массива. Чтобы их ввести, нужно выделить диапазон, в строку формул ввести фомулу без фигурных скобок и нажать ctrl±shift+enter
Написанные мной формулы - формулы массива. Чтобы их ввести, нужно выделить диапазон, в строку формул ввести фомулу без фигурных скобок и нажать ctrl±shift+enterkrosav4ig
Serge_007, скажите пожалуйста можно ли эти первые две формулы объединить в одну?
Graceless, ради интереса заглянул в ваш макрос... у меня возникли большие сомнения по поводу строки [vba]
Код
If Target.Count > 1 Then Target.Delete
[/vba] чтобы было понятнее переведу ее на руссий язык [vba]
Код
ЕСЛИ в выделенном диапазоне более 1 ячейки ТО удалить первую ячейку выделенного диапазона со сдвигом влево
[/vba] дело в том, что в Range("E39:G41") все ячейки являются частью объединенного диапазона и привыборе любой из них на этой строке кода будет происходить удаление
заглянул в module1 и мне стало как-то непосебе настоятельно рекомендую все что там написано заменить на чтото типа этого [vba]
Код
Sub Clear_all() ActiveSheet.Unprotect Application.ScreenUpdating = False Dim rngs As Variant Dim rng, rng2 As Range rngs = Array("B39", "C4", "H4", "C6", "C7", "C8", "C9", "C10", "C12", _ "C13", "H12", "H8", "C17", "E17:H19", "C21", "E21:H23", "C25", "E25:H31", _ "C39", "E39:H44", "D49:D54", "D56:D58", "B62:E62", "B63:E63", "B66:E66", _ "B67:E67", "H33:H37", "F62:I62", "F67:I67", "D64:E64", "D68:E68", "H64:I64", _ "C2") Set rng = Range(rngs(0)) Dim i As Integer For i = 0 To UBound(rngs) For Each cell In Range(rngs(i)) If cell.MergeCells Then Set rng = Union(rng, cell.MergeArea) Else Set rng = Union(rng, cell) End If Next Next rng.ClearContents Application.ScreenUpdating = True ActiveSheet.Protect End Sub
[/vba]
и еще несколько слов про использование Worksheet_Change, Workbook_SheetChange, Worksheet_SelectionChange, Workbook_SheetSelectionChange
Worksheet_Change, Workbook_SheetChange - это процедуры, которые выполняются при любом изменении ячеек листа. Worksheet_Change запускается только при изменении на листе, в модуль которого она прописана, если она прописана не в модуль листа, оно работать не будет. Workbook_SheetChange запускается при изменениии на любом листе и эта процедура должна быть прописана в модуль книги (в вашем случае ЦяКнига). Если не планируется, что в книге будет множество однотипных листов, то я бы посоветовал перенести эту процедуру в модуль листа.
та же картина и с Worksheet_SelectionChange, Workbook_SheetSelectionChange Worksheet_SelectionChange запускается при изменении адреса активной ячейки в том листе, в модуль которого она прописана. Workbook_SheetSelectionChange запускается при изменении адреса активной ячейки в любом листе и точно так же как и Workbook_SheetChange должна быть прописана в модуль книги (в вашем случае ЦяКнига). И так же если не планируется, что в книге будет множество однотипных листов, то я бы посоветовал перенести эту процедуру в модуль листа.
небольшая поправка: в диапазоне O76:O85 формулу нужно заменить на
Serge_007, скажите пожалуйста можно ли эти первые две формулы объединить в одну?
Graceless, ради интереса заглянул в ваш макрос... у меня возникли большие сомнения по поводу строки [vba]
Код
If Target.Count > 1 Then Target.Delete
[/vba] чтобы было понятнее переведу ее на руссий язык [vba]
Код
ЕСЛИ в выделенном диапазоне более 1 ячейки ТО удалить первую ячейку выделенного диапазона со сдвигом влево
[/vba] дело в том, что в Range("E39:G41") все ячейки являются частью объединенного диапазона и привыборе любой из них на этой строке кода будет происходить удаление
заглянул в module1 и мне стало как-то непосебе настоятельно рекомендую все что там написано заменить на чтото типа этого [vba]
Код
Sub Clear_all() ActiveSheet.Unprotect Application.ScreenUpdating = False Dim rngs As Variant Dim rng, rng2 As Range rngs = Array("B39", "C4", "H4", "C6", "C7", "C8", "C9", "C10", "C12", _ "C13", "H12", "H8", "C17", "E17:H19", "C21", "E21:H23", "C25", "E25:H31", _ "C39", "E39:H44", "D49:D54", "D56:D58", "B62:E62", "B63:E63", "B66:E66", _ "B67:E67", "H33:H37", "F62:I62", "F67:I67", "D64:E64", "D68:E68", "H64:I64", _ "C2") Set rng = Range(rngs(0)) Dim i As Integer For i = 0 To UBound(rngs) For Each cell In Range(rngs(i)) If cell.MergeCells Then Set rng = Union(rng, cell.MergeArea) Else Set rng = Union(rng, cell) End If Next Next rng.ClearContents Application.ScreenUpdating = True ActiveSheet.Protect End Sub
[/vba]
и еще несколько слов про использование Worksheet_Change, Workbook_SheetChange, Worksheet_SelectionChange, Workbook_SheetSelectionChange
Worksheet_Change, Workbook_SheetChange - это процедуры, которые выполняются при любом изменении ячеек листа. Worksheet_Change запускается только при изменении на листе, в модуль которого она прописана, если она прописана не в модуль листа, оно работать не будет. Workbook_SheetChange запускается при изменениии на любом листе и эта процедура должна быть прописана в модуль книги (в вашем случае ЦяКнига). Если не планируется, что в книге будет множество однотипных листов, то я бы посоветовал перенести эту процедуру в модуль листа.
та же картина и с Worksheet_SelectionChange, Workbook_SheetSelectionChange Worksheet_SelectionChange запускается при изменении адреса активной ячейки в том листе, в модуль которого она прописана. Workbook_SheetSelectionChange запускается при изменении адреса активной ячейки в любом листе и точно так же как и Workbook_SheetChange должна быть прописана в модуль книги (в вашем случае ЦяКнига). И так же если не планируется, что в книге будет множество однотипных листов, то я бы посоветовал перенести эту процедуру в модуль листа.krosav4ig
Ну дык ставьте kingsoft office и будет вам счастье. Kingsoft office free(google play) англ. условное форматирование в нем вполне себе нормально работает. Если нужна русская версия, то выбирайте тут. А про VBA на Android пока остается только мечтать.
Ну дык ставьте kingsoft office и будет вам счастье. Kingsoft office free(google play) англ. условное форматирование в нем вполне себе нормально работает. Если нужна русская версия, то выбирайте тут. А про VBA на Android пока остается только мечтать.krosav4ig
Private Sub del_0() Dim rng As Range With ThisWorkbook.Worksheets("день").Range("C:C") Set rng = .Find(0, , LookIn:=xlValues, lookat:=xlWhole) If Not rng Is Nothing Then Do rng.EntireRow.Delete Set rng = .FindNext() Loop While Not rng Is Nothing End If End With End Sub
[/vba]
[vba]
Код
Private Sub del_0() Dim rng As Range With ThisWorkbook.Worksheets("день").Range("C:C") Set rng = .Find(0, , LookIn:=xlValues, lookat:=xlWhole) If Not rng Is Nothing Then Do rng.EntireRow.Delete Set rng = .FindNext() Loop While Not rng Is Nothing End If End With End Sub