Извлечение значений в пределах дат и диапазонов зон

Чтобы автоматизировать ручную задачу, я создал следующий код. Поскольку я никогда не писал программу такого размера, мне любопытно, является ли использование переменных, а также решений наиболее оптимальным способом обработки.

В этой программе пользователь выберет год, месяц и зону. Эти варианты используются для сужения месяца в течение года, календарных недель в течение месяца и состояний в зонах. Эти суженные диапазоны будут извлекать данные в пределах этих параметров и помещать их в основной отчет.

Все в целом, надеясь найти, лучше ли использовать переменные, а также узнать, являются ли они лучшими методами сужения диапазонов.

Sub TransactionCT_Reference()

Dim wb As Workbook, wb2 As Workbook
Dim ws As Worksheet, ws2 As Worksheet
Dim yRow As Variant
Dim frstMrow As Long, scndMrow As Long, _
    frstYrow As Long, scndYrow As Long, _
    frstZrow As Long, scndZrow As Long, _
    frstSrow As Long, scndSrow As Long, _
    frstCWrow As Long, scndCWrow As Long, cwCount As Long, _
    unkRow As Long, mCount As Long
Dim frstBZday As Double, frstCLday As Double, scndBZday As Double, _
    scndCLday As Double
Dim frstMname As String, scndMname As String, _
    frstZname As String, scndZname As String, _
    cwName1 As String, cwName2 As String, drName As String, unk As String
Dim mRng As Range, yRng1 As Range, yRng2 As Range, _
    zRng1 As Range, zRng2 As Range, sRng As Range, _
    cell As Range, cell2 As Range, xlsRng As Range, _
    sRng1 As Range, sRng2 As Range, sRng3 As Range, _
    dRng0 As Range, dRng13 As Range, dRng14 As Range, _
    dRng15 As Range, dRng16 As Range, dRng17 As Range, _
    dRng18 As Range, dRng19 As Range, dRng22 As Range, _
    dRng23 As Range, ws2Rng As Range

    ' Change to MASTER_Choices Cycle Time
    Set wb = Workbooks("MASTER_Choices Cycle Time - In Work VBA Changes.xlsm")
    ' Change to "03 - Data"
    Set ws = wb.Worksheets("03 - Data 2")

    ws.Activate

    'Set Year value
    yRow = ws.Cells(lastrow + 2, 5)
    ' Set Month value
    frstMname = ws.Cells(lastrow + 2, 4)
    ' Set Zone value
    frstZname = ws.Cells(lastrow + 2, 11)

    ' Dynamically find first iteration of 2015, 2016, and 2017
    On Error Resume Next
        frstYrow = Application.WorksheetFunction.Match(yRow, ws.Range("AE:AE"), 0)
        scndYrow = Application.WorksheetFunction.Match(yRow + 1, ws.Range("AE:AE"), 0)
    On Error GoTo 0

    ' Set full range of results that show year = yRow
    Set yRng1 = ws.Range("AE" & frstYrow, "AI" & scndYrow - 1)
    ' Set year column of results that show year = yRow
    Set yRng2 = ws.Range("AF" & frstYrow, "AF" & scndYrow - 1)

    If frstMname = "Jan" Then
        scndMname = "Feb"
    ElseIf frstMname = "Feb" Then
        scndMname = "Mar"
    ElseIf frstMname = "Mar" Then
        scndMname = "Apr"
    ElseIf frstMname = "Apr" Then
        scndMname = "May"
    ElseIf frstMname = "May" Then
        scndMname = "Jun"
    ElseIf frstMname = "Jun" Then
        scndMname = "Jul"
    ElseIf frstMname = "Jul" Then
        scndMname = "Aug"
    ElseIf frstMname = "Aug" Then
        scndMname = "Sep"
    ElseIf frstMname = "Sep" Then
        scndMname = "Oct"
    ElseIf frstMname = "Oct" Then
        scndMname = "Nov"
    ElseIf frstMname = "Nov" Then
        scndMname = "Dec"
    ElseIf frstMname = "Dec" Then
        scndMname = "End"
    Else
        MsgBox "No Month Found"
    End If

    ' Establish Range of Month, find first and last row of Month
    On Error Resume Next
        frstMrow = Application.WorksheetFunction.Match(frstMname, yRng2, 0)
        scndMrow = Application.WorksheetFunction.Match(scndMname, yRng2, 0)
    On Error GoTo 0

    'Within yRng1 narrow range to selected Month
    Set mRng = yRng1.Range("A" & frstMrow, "E" & scndMrow - 1)

    ' Count number of iterations of named Month within mRng
    mCount = Application.WorksheetFunction.CountIf(mRng, frstMname)

    ' Open file <Zone>.xls located in Desktop>Projects>NuGen
    Workbooks.Open Filename:="C:\Users\uswanw16\Desktop\Projects\NuGen\" & frstZname & ".xls"

    Set wb2 = Workbooks(frstZname & ".xls")
    Set ws2 = wb2.Worksheets(1)

    ws2.Activate

    ' Removing all " " from text as NG report has " " and then text
    ws2.Cells.Replace What:=" ", Replacement:=ClearContents, LookAt:=xlPart, SearchOrder:= _
    xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False

    ' Set Range to clear all blank cells
    unk = "Unknown"
    unkRow = Application.WorksheetFunction.Match(unk, ws2.Range("B:B"), 0)
    Set ws2Rng = ws2.Range("B1", "B" & unkRow)

    ' Copy data w/in "B:B"; Paste to ws2.Range K:K
    ws2.Range("K:K") = ws2Rng.Value
    ' Remove duplicates
    ws2.Range("K:K").RemoveDuplicates Columns:=1, Header:=xlNo

    ' Run new frstZname, scndZname to set zone zRng2
    If frstZname = "Central" Then
        scndZname = "East"
    ElseIf frstZname = "East" Then
        scndZname = "West"
    ElseIf frstZname = "West" Then
        scndZname = "Unknown"
    Else
        MsgBox "No Zone Found"
    End If

    On Error Resume Next
        frstZrow = Application.WorksheetFunction.Match(frstZname, ws2.Range("K:K"), 0)
        scndZrow = Application.WorksheetFunction.Match(scndZname, ws2.Range("K:K"), 0)
    On Error GoTo 0

    ' Establish Range of Zone, find first and last row of Zone
    Set zRng1 = ws2.Range("K" & frstZrow + 1, "K" & scndZrow - 1)

    ' Count the number of states within the zone
    zCount = Application.WorksheetFunction.CountIf(zRng1, frstZname)

    Set cell = zRng1(1, 1)

    i = 1
    k = 0

    For Each cell In zRng1
        'Narrow each range to given state
        On Error Resume Next
        Set cell = zRng1(i, 1)
            'Find state in xls
            frstSrow = Application.WorksheetFunction.Match(cell, ws2.Range("B:B"), 0)
        Set cell = zRng1(i + 1, 1)
            'Find second state in xls
            scndSrow = Application.WorksheetFunction.Match(cell, ws2.Range("B:B"), 0)
        On Error GoTo 0

        On Error Resume Next
            ' Create range State for month
            Set sRng1 = ws2.Range("C" & frstSrow, "C" & scndSrow - 1)
        On Error GoTo 0

        'Find week data and transfer to MASTER sheet
        On Error Resume Next
        For j = 1 To mCount
            Set dRng0 = ws2.Cells(100, 100)
            Set dRng13 = ws.Cells(lastrow + j + 1 + 1 + mCount * k, 1)
            Set dRng14 = ws.Cells(lastrow + j + 1 + 1 + mCount * k, 2)
            Set dRng15 = ws.Cells(lastrow + j + 1 + 1 + mCount * k, 3)
            Set dRng16 = ws.Cells(lastrow + j + 1 + 1 + mCount * k, 4)
            Set dRng17 = ws.Cells(lastrow + j + 1 + 1 + mCount * k, 5)
            Set dRng18 = ws.Cells(lastrow + j + 1 + 1 + mCount * k, 6)
            Set dRng19 = ws.Cells(lastrow + j + 1 + 1 + mCount * k, 7)
            Set dRng22 = ws.Cells(lastrow + j + 1 + 1 + mCount * k, 10)
            Set dRng23 = ws.Cells(lastrow + j + 1 + 1 + mCount * k, 11)
            'Find CW on MASTER and set to cwName1
            cwName1 = mRng(j, 3)
            'Calendar Week ##
            cwName2 = mRng(j, 4)
            ' Date Range
            drName = mRng(j, 5)
            'Find row number of cwName1 within sRng1
            'Search sRng1 to find count of mRng(j, 3)
            cwCount = Application.WorksheetFunction.CountIf(sRng1, cwName1)
            'If count of cwCount within sRng1(j, 3) > 1, then average both values
            frstCWrow = Application.WorksheetFunction.Match(cwName1, sRng1, 0)
            ' Date
            dRng13.Value = cwName1
            'Calendar Week
            dRng14.Value = cwName2
            'Date Range
            dRng15.Value = drName
            'Month
            dRng16.Value = frstMname
            'Year
            dRng17.Value = yRow
            'Biz Range - from vLookup in getEstimate Table
            'Cal Range - from vLookup in getEstimate Table
            'State
            dRng22.Value = cell(0)
            'Zone
            dRng23.Value = frstZname
            'Check to see if CW occurs more than once in range, if so average
            If cwCount > 1 Then
                Set sRng2 = sRng1.Find(What:=cwName1)
                frstBZday = sRng2.Cells(1, 2).Text
                frstCLday = sRng2.Cells(1, 3).Text
                Set sRng2 = sRng1.FindNext(sRng2)
                scndBZday = sRng2.Cells(1, 2)
                scndCLday = sRng2.Cells(1, 3)
                dRng18 = (frstBZday + scndBZday) / 2
                dRng19 = (frstCLday + scndCLday) / 2
            'If count of sRng1(j, 3) = 1, then do below:
            ' If CW ## is found in range
            ElseIf frstCWrow <> "0" Then
                Set sRng3 = sRng1.Range("A" & frstCWrow)
                'In Work - Biz Days; 18
                dRng0.Copy
                sRng3.Cells(1, 2).PasteSpecial Paste:=xlPasteValues, Operation:=xlPasteSpecialOperationAdd
                dRng18.Value = sRng3.Cells(1, 2)
                'In Work - Cal Days; 19
                dRng0.Copy
                sRng3.Cells(1, 3).PasteSpecial Paste:=xlPasteValues, Operation:=xlPasteSpecialOperationAdd
                dRng19.Value = sRng3.Cells(1, 3)
            ' If CW is not found in range
            ElseIf frstCWrow = "0" Then
                'In Work - Cal Days; 18
                dRng18.Value = "Null"
                'In Work - Cal Days; 19
                dRng19.Value = "Null"
            Else
                MsgBox "No Calendar Week Found"
            End If
            ' Reset CW in case it is not found
            frstCWrow = 0
       Next j
        On Error GoTo 0
        i = i + 1
        k = k + 1
    Next cell

    wb2.Close False

End Sub

С публичной функцией lastrow:

Public Function lastrow()

    Set wb = Workbooks("MASTER_Choices Cycle Time - In Work VBA Changes.xlsm")
    Set ws = wb.Worksheets("03 - Data 2")

    lastrow = ws.ListObjects("Table501").Range.Rows.Count

End Function
11 голосов | спросил PlainsWind 16 WedEurope/Moscow2015-12-16T20:32:53+03:00Europe/Moscow12bEurope/MoscowWed, 16 Dec 2015 20:32:53 +0300 2015, 20:32:53

2 ответа


11

Мальчику есть много, о чем можно поговорить здесь.

Прежде всего, если Option Explicit не находится в верхней части каждого модуля кода, перейдите к инструментам -> Параметры -> Требовать объявление переменной. Это будет автоматически вставлять его с этого момента (я, честно говоря, не знаю, почему это было в первую очередь).


Теперь я хочу указать на все то хорошее, что вы уже делаете:

  • Явно объявляю ваши переменные как тип. Это помогает предотвратить всевозможные непреднамеренные ошибки, потому что VBE скажет вам, когда вы делаете что-то, что вы, очевидно, не собираетесь повторно: типы данных.

  • Используя _, чтобы упорядочить ваш код более легко читаемым способом.

  • Допустимое использование комментариев для документа /указателя логики вашего кода. Это может быть намного лучше (о чем я расскажу подробнее), но их достаточно, чтобы сделать ваш текущий код достаточно простым для понимания и понимания.

  • Собственно, используя объектную модель VBA. Множество кодов начинающих усеяно множеством повторений sheets("sheet name") и т. Д. Здесь вы создаете свои рабочие листы /книги, а затем ссылаетесь на те, которые означает, что, если, например, изменилось название вашей книги, вам нужно будет только изменить его в одном месте в вашем коде.

  • Определение значений динамически, а не жесткого кодирования. Наличие жесткого кода - это огромный источник ошибок, головных болей и потерянного времени разработчика для постоянных изменений. Все, что может быть определено динамически вообще, должно быть таким большим пальцем вверх для этого.

  • Рефакторинг . Вы могли бы (и должны) делать это намного больше. Взятие маленькой вещи (поиск последней строки) и перемещение ее в отдельную процедуру - основа всего хорошего кода. Так хорошо сделано.

Вкратце: у вас на самом деле есть основа для многих концепций, которые вам нужны, чтобы стать отличным разработчиком. Теперь, когда это не в порядке:


Нейминг

Хорошее, информативное именование - одна из наиболее важных, если не , наиболее важной составляющей разработки программного обеспечения. Кодирование составляет примерно 80% кода чтения, и только 20% его записывают. И это только становится еще более наклонным к чтению, так как ваш код становится все более сложным. Таким образом, практически во всех случаях самая важная часть вашего кода заключается в том, как легко кто-то может понять, что он делает.

Переменные имена должны быть описательными, краткими и, прежде всего, однозначными . И они должны звучать так, как они.

НЕТ ваших переменных имеют хорошие имена. Едва ли у любого из них есть даже приемлемые имена.

Вы видите это?

  

Set dRng13 = ws.Cells(lastrow + j + 1 + 1 + mCount * k, 1)

Как насчет этого?

  

scndBZday = sRng2.Cells(1, 2)

Совершенно непонятно. Если вы считаете, что один из выходов вашего кода был неправильным, где бы вы даже начали пытаться выяснить, что все делает?

Мой совет: До тех пор, пока у вас не будет опыта, ошибайтесь на стороне более подробных имен. Даже если это означает запись переменных, называемых thingWhichRepresentsOutputOfThatThing или процедур, называемых FunctionToDoThisThingBasedOnThatAssumption. Конечно, больно писать (проконсультироваться, использовать Ctrl + пространство для автоматического заполнения любых объявленных имен переменных, процедур, методов и т. Д.), И это выглядит беспорядочно, но поверьте мне, это спасет вас (или кто бы то ни было должен поддерживать ваш код) так много проблем по дороге.

Некоторые примеры:

wb1, wb2 не являются хорошими именами переменных. Как я могу помнить, что это такое? Особенно, если есть больше, чем просто 2, чтобы отслеживать. wbMasterChoices и wbDataOutput по-прежнему не велики, но они намного более наглядны. Поскольку у вас есть больше знаний о том, что они на самом деле, вы, вероятно, можете подумать о некоторых даже лучшеимена.

  

frstMRow, frstYRow, frstDRow

и т.д.. Сократить . Не . Просто назовите их, что они firstMonthRow, firstYearRow, firstDayRow. это всего лишь несколько дополнительных персонажей, но это намного проще и легче на мозге.

Не используйте нумерованные переменные. Иногда есть веские основания для этого. Но они редки. Сверху вашей головы, какой фрагмент данных drng19 представляет? Как насчет ws2rng? Или zrng2? Если вы не можете сказать, что представляет переменная, просто прочитав ее имя, тогда она недостаточно хорошо названа.

Ваши диапазоны - беспорядок. Они кричат ​​о некоторых описательных именах.

yrng1, yrng2 до yearDataTable, ---- +: = 17 = + ----

yearIndexColumn до mRng

monthDataTable до mCount

Чем легче следовать?

monthRowCount

или

`mCount = Application.WorksheetFunction.CountIf(mRng, frstMname)`

Обратите внимание на то, что я полностью вывел эту строку из контекста, и все же довольно очевидно, что все переменные, что они представляют и что происходит.

Добавленный бонус: Описательные имена очень трудно ошибочно. Принимая во внимание, что если ваш палец скользит, и вы случайно написали monthRowCount = Application.WorksheetFunction.CountIf(monthDataTable, firstMonthName) , когда вы намеревались ввести zrng, ваша программа может дать вам неправильный результат, и вы всегда будете пытаться выяснить, что происходит не так, если вы даже поняли в первую очередь.


Рефакторинг

Следующая часть написания отличного кода разбивает вашу программу на маленькие логические биты. Как правило, в любое время у вас возникнет соблазн написать комментарий вроде

srng

Вы должны создать отдельную суб /функцию, передать любые необходимые ей параметры, а затем отделить свою логику.

В этом случае что-то вроде

`'Find week data and transfer to MASTER sheet`

В качестве примера, это основная часть моего недавнего проекта.

Dim dataArray as variant
    dataArray = array()

dataArray = GetWeekData(arg, arg, arg)

PrintWeekDataToSheet dataArray, ws

Обратите внимание на полное отсутствие комментариев, и все же все абсолютно ясно. Вообще говоря, комментарии должны быть необходимы только для описания * почему * вы делали что-то определенным образом. Каждый раз, когда вы обнаруживаете, что пишете комментарии, чтобы описать *, что вы делаете, попробуйте переименовать /реорганизовать код, чтобы сделать его излишним.


Другие вещи, которые выпрыгивают на меня

Sub BtnSort_Click()

'/====================================================================================================
'/  Author: Zak Armstrong
'/
'/  Description:
'/  For the active sheet, finds the data Table and sortKey columns using headers.
'/  Sorts clients based on payment frequency, then payment day, then Client Name.
'/  Colours rows depending on their payment frequency.
'/====================================================================================================

    StoreApplicationSettings

    DisableApplicationSettings

        Dim ws_this As Worksheet
        Set ws_this = ActiveSheet

        Dim tableRange As Range
        Set tableRange = GetTableRange(ws_this)

        ValidateTableHeaders ws_this, tableRange

        Dim paymentFrequencyColNum As Long, paymentDayColNum As Long, clientNameColNum As Long

        FindColumnIndexes ws_this, tableRange, paymentFrequencyColNum, paymentDayColNum, clientNameColNum

        SortTableRange ws_this, tableRange, paymentFrequencyColNum, paymentDayColNum, clientNameColNum

        FormatTableRange ws_this, tableRange, paymentFrequencyColNum

    RestoreApplicationSettings

End Sub

Как вы, возможно, поняли, это просто беспорядочно.

Прежде всего, если вы когда-либо обнаруживаете, что используете несколько If frstMname = "Jan" Then scndMname = "Feb" ElseIf frstMname = "Feb" Then scndMname = "Mar" ElseIf frstMname = "Mar" Then scndMname = "Apr" ElseIf frstMname = "Apr" Then scndMname = "May" ElseIf frstMname = "May" Then scndMname = "Jun" ElseIf frstMname = "Jun" Then scndMname = "Jul" ElseIf frstMname = "Jul" Then scndMname = "Aug" ElseIf frstMname = "Aug" Then scndMname = "Sep" ElseIf frstMname = "Sep" Then scndMname = "Oct" ElseIf frstMname = "Oct" Then scndMname = "Nov" ElseIf frstMname = "Nov" Then scndMname = "Dec" ElseIf frstMname = "Dec" Then scndMname = "End" Else MsgBox "No Month Found" End If s, a ElseIf почти всегда является лучшей идеей.

Итак:

Select ... Case

В этом случае я бы справился с этим, преобразовывая свой месяц в индекс, а затем добавляя 1. Проверка правильной строки месяца сложна, но я бы это обработал:

Select Case firstMonthName

    Case Is = "Jan"
        secondMonthName = "Feb"

    Case Is = "Feb"
        secondMonthName = "Mar"

    ...

    Case Else
        MsgBox "Could not identify """ & firstMonthName & """ as month"
        Exit Sub

End Select

Это также имеет то преимущество, что вы можете использовать «Ян», «Январь» и т. д. Пока это допустимый идентификатор месяца.


Dim ixMonth As Long, testVar as Variant

On Error Resume Next
testVar = CDate("01/" & firstMonthName & "/2000")
On Error Goto 0

If IsDate(testVar) then 
    ixMonth = Month(testVar)

    If ixMonth = 12 Then
        secondMonthName = "End"
    Else
        secondMonthName = MonthName(ixMonth + 1)
    End If
Else
    '/ Error handling
End If

Вы намерены изменить E.G. ' Removing all " " from text as NG report has " " and then text ws2.Cells.Replace What:=" ", Replacement:=ClearContents, LookAt:=xlPart, SearchOrder:= _ xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=Fals в "Some Text"? Если вы хотите избавиться от ведущих /конечных пробелов, как насчет функции "SomeText"?


Trim()

On Error Resume Next Set cell = zRng1(i, 1) 'Find state in xls frstSrow = Application.WorksheetFunction.Match(cell, ws2.Range("B:B"), 0) Set cell = zRng1(i + 1, 1) 'Find second state in xls scndSrow = Application.WorksheetFunction.Match(cell, ws2.Range("B:B"), 0) On Error GoTo 0 не используется легко. Его следует избегать везде, где это возможно, особенно когда вы неопытен. Если вы * * должны использовать его, он должен быть максимально ограниченным.

Это то, что обычно используется в качестве действительного использованиякак:

On Error Resume Next

Наличие более одной строки с отключенными ошибками уже является большим предупреждающим знаком. Наличие целых фрагментов кода, работающего с отключенными ошибками, активно Опасно , потому что, если ошибки * делают *, то они не будут обрабатываться, и они будут сидеть там молча, разлагая ваши результаты .

Подтвердите свои переменные. Проверьте края. И если после всего этого вам еще нужно отключить ошибки для конкретной операции, сохраните ее и немедленно обработайте ошибку, которую вы ожидаете.

ответил Kaz 16 WedEurope/Moscow2015-12-16T21:01:42+03:00Europe/Moscow12bEurope/MoscowWed, 16 Dec 2015 21:01:42 +0300 2015, 21:01:42
7

Давайте немного поговорим об этом.

If frstMname = "Jan" Then
    scndMname = "Feb"
ElseIf frstMname = "Feb" Then
    scndMname = "Mar"
ElseIf frstMname = "Mar" Then
    scndMname = "Apr"
ElseIf frstMname = "Apr" Then
    scndMname = "May"
ElseIf frstMname = "May" Then
    scndMname = "Jun"
ElseIf frstMname = "Jun" Then
    scndMname = "Jul"
ElseIf frstMname = "Jul" Then
    scndMname = "Aug"
ElseIf frstMname = "Aug" Then
    scndMname = "Sep"
ElseIf frstMname = "Sep" Then
    scndMname = "Oct"
ElseIf frstMname = "Oct" Then
    scndMname = "Nov"
ElseIf frstMname = "Nov" Then
    scndMname = "Dec"
ElseIf frstMname = "Dec" Then
    scndMname = "End"
Else
    MsgBox "No Month Found"
End If

Итак, во-первых, я рад видеть, что вы справились с неожиданным случаем. Проблема в том, что вы плохо справлялись с этим. Может ли ваш код работать правильно, если не найден месяц? Я сомневаюсь в этом. Вероятно, вы должны отобразить это окно с значком ошибки и прервать его, выйдя из подпрограммы прямо там.

Другая проблема - явная повторяемость кода. Ваши сокращения в течение нескольких месяцев могут быть очень хорошо представлены в Словаре.

Dim months As Scripting.Dictionary
months = New Scripting.Dictionary

months.Add "Jan", 1
months.Add "Feb", 2
' etc. 

Тогда вы можете установить второй месяц примерно так.

If Not months.Exists(firstMonthName) Then
    MsgBox "Blow Up!"
    Exit Sub
End If

secondMonthName = months.Keys(months(firstMonthName))

Итак, я знаю, что это не очень очевидно, но это работает, потому что Keys возвращает нулевой индексный массив, но наши номера месяца начинаются с 1. Возможно, было бы немного легче читать, если бы мы ввели переменную.

Dim secondMonthIndex = months(firstMonthName)
secondMonthName = months.Keys(secondMonthIndex)

В любом случае этот метод позволяет нам удалить дубликат и строковый литерал, используя таблицу поиска.

ответил RubberDuck 17 ThuEurope/Moscow2015-12-17T05:12:15+03:00Europe/Moscow12bEurope/MoscowThu, 17 Dec 2015 05:12:15 +0300 2015, 05:12:15

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132