﻿Attribute VB_Name = "SquareClickStandard"
Option Explicit

' SquareClick Standard 1.4 TEST (Excel 2019/2021 desktop, Windows)
' Original form controls remain VISIBLE; their native captions stay untouched.
' Consent is stored in the normal workbook's custom document properties.
' Two temporary shapes per checkbox: transparent click layer + vector □/■ face.
' No network calls, Shell commands, or file I/O. Save events handled by SquareClickSession.

Private Const PROP_CONSENT As String = "SCSTD_CheckboxConsent_v1"
Private Const PROP_YES As String = "yes"
Private Const PROP_NO As String = "no"
Private Const TAG_CB As String = "SCSTD|CB|"  ' clickable hit area (also old 1.3 tag)
Private Const TAG_BOX As String = "SCSTD|BOX|" ' □/■ geometry
' Adjust only these values to calibrate square alignment (points, NOT pixels).
Private Const SC14_MARK_SIZE_PT As Double = 8.7
Private Const SC14_MARK_LEFT_PT As Double = 4
Private Const SC14_MARK_TOP_PT As Double = 0
Private Const MAX_PER_SHEET As Long = 400
Private mBusy As Boolean
' Workbooks where Cancel was selected during this Excel session.
' Unlike the saved Yes/No property, this collection is NOT saved in the workbook.
Private mDeferredWorkbooks As Collection

Private Function SCStd_IsDeferred(ByVal wb As Excel.Workbook) As Boolean
    Dim item As Excel.Workbook
    If mDeferredWorkbooks Is Nothing Then Exit Function
    For Each item In mDeferredWorkbooks
        If item Is wb Then
            SCStd_IsDeferred = True
            Exit Function
        End If
    Next item
End Function

Private Sub SCStd_Defer(ByVal wb As Excel.Workbook)
    If mDeferredWorkbooks Is Nothing Then Set mDeferredWorkbooks = New Collection
    If Not SCStd_IsDeferred(wb) Then mDeferredWorkbooks.Add wb
End Sub

Public Sub SCStd_ProcessWorkbook(ByVal wb As Excel.Workbook)
    Dim consent As String
    Dim answer As VbMsgBoxResult
    Dim noConfirmed As Boolean
    Dim candidateCount As Long
    Dim ws As Excel.Worksheet
    Dim selectedSheet As Object

    If mBusy Then Exit Sub
    If wb Is Nothing Then Exit Sub
    If wb Is ThisWorkbook Then Exit Sub
    If wb.ReadOnly Then Exit Sub

    On Error GoTo ErrorHandler
    consent = SCStd_ReadConsent(wb)

    If consent = PROP_NO Then Exit Sub

    If consent = PROP_YES Then
        Set selectedSheet = wb.ActiveSheet
        If Not selectedSheet Is Nothing Then
            If TypeOf selectedSheet Is Excel.Worksheet Then
                SCStd_ApplySheet selectedSheet
            End If
        End If
        Exit Sub
    End If

    If SCStd_IsDeferred(wb) Then Exit Sub

    candidateCount = SCStd_CountEligible(wb)
    If candidateCount = 0 Then Exit Sub

    mBusy = True
    answer = MsgBox( _
        "このブックのチェックボックスを□・■表示に変更しますか？" & vbCrLf & vbCrLf & _
        "対象：従来型フォームコントロール（" & CStr(candidateCount) & "個）" & vbCrLf & _
        "元のチェックボックスは残し、チェック部分に□・■を重ねます。" & vbCrLf & _
        "マクロ割当済み・ActiveX・保護シートのものは変更しません。" & vbCrLf & vbCrLf & _
        "はい：□・■表示に変更する" & vbCrLf & _
        "いいえ：この文書ではSquareClickを一切適用しない（再確認あり）" & vbCrLf & _
        "キャンセル：今回は何も変更しない", _
        vbYesNoCancel + vbQuestion, "SquareClick Standard（初回のみ）")
    ' Keep the prompt guard set while the second dialog is open.
    If answer = vbNo Then
        noConfirmed = SCStd_ConfirmNoForWorkbook()
    End If
    mBusy = False

    Select Case answer
        Case vbYes
            If Not SCStd_WriteConsent(wb, PROP_YES) Then
                MsgBox "ブックに確認結果を記録できなかったため、処理を中止しました。", _
                       vbExclamation, "SquareClick Standard"
                Exit Sub
            End If
            SCStd_ApplyWorkbook wb
        Case vbNo
            If Not noConfirmed Then
                ' Second-stage Cancel: do not write a property or apply UI.
                ' Avoid immediate repeated prompts from WorkbookActivate.
                SCStd_Defer wb
                Exit Sub
            End If
            ' Fully clean the runtime UI before saving a permanent No choice.
            If Not SCStd_ChangeMode(wb, PROP_NO) Then
                SCStd_Defer wb
            End If
        Case vbCancel
            ' Once per open workbook: no repeated prompts on Activate/SheetActivate.
            ' The workbook remains unchanged. Closing/reopening makes a new instance.
            SCStd_Defer wb
    End Select
    Exit Sub

ErrorHandler:
    mBusy = False
    MsgBox "初期処理エラー " & Err.Number & vbCrLf & Err.Description, _
           vbExclamation, "SquareClick Standard"
End Sub

Private Function SCStd_ConfirmNoForWorkbook() As Boolean
    ' MsgBox cannot offer exactly [Yes] and [Cancel]. A small UserForm does.
    Dim dlg As SCStdNoConfirm
    On Error GoTo Failed
    Set dlg = New SCStdNoConfirm
    dlg.Show vbModal
    SCStd_ConfirmNoForWorkbook = dlg.Confirmed
    Unload dlg
    Exit Function
Failed:
    On Error Resume Next
    If Not dlg Is Nothing Then Unload dlg
    MsgBox "確認画面を表示できませんでした。設定は変更しません。" & vbCrLf & _
           Err.Description, vbExclamation, "SquareClick Standard"
End Function

Public Function SCStd_AllowListForWorkbook(ByVal wb As Excel.Workbook) As Boolean
    ' The No decision is always for the entire workbook, not only checkboxes.
    ' For existing list-only files with no form checkboxes, preserve legacy
    ' auto-operation. Workbooks awaiting a form-checkbox decision stay untouched.
    Dim choice As String
    On Error GoTo Denied
    If wb Is Nothing Then Exit Function
    If wb Is ThisWorkbook Then Exit Function
    choice = SCStd_ReadConsent(wb)
    Select Case choice
        Case PROP_NO
            Exit Function
        Case PROP_YES
            SCStd_AllowListForWorkbook = True
        Case Else
            If SCStd_IsDeferred(wb) Then Exit Function
            SCStd_AllowListForWorkbook = (SCStd_CountEligible(wb) = 0)
    End Select
    Exit Function
Denied:
    SCStd_AllowListForWorkbook = False
End Function

Private Sub SCStd_RemoveTemporaryUI(ByVal wb As Excel.Workbook)
    Dim ws As Excel.Worksheet
    On Error Resume Next
    For Each ws In wb.Worksheets
        SCStd_CleanSheet ws
        SquareClickCore.SquareClick_CleanSheet ws
    Next ws
    On Error GoTo 0
End Sub

Private Function SCStd_ReadConsent(ByVal wb As Excel.Workbook) As String
    On Error GoTo NotFound
    SCStd_ReadConsent = CStr(wb.CustomDocumentProperties(PROP_CONSENT).value)
    Exit Function
NotFound:
    SCStd_ReadConsent = vbNullString
End Function

Public Function SCStd_GetConsentForUI(ByVal wb As Excel.Workbook) As String
    ' Return yes/no/unset; used only to display the settings dialog.
    If wb Is Nothing Then Exit Function
    SCStd_GetConsentForUI = SCStd_ReadConsent(wb)
End Function

Private Function SCStd_WriteConsent(ByVal wb As Excel.Workbook, ByVal choice As String) As Boolean
    Dim p As Object
    On Error GoTo Failed
    On Error Resume Next
    Set p = wb.CustomDocumentProperties(PROP_CONSENT)
    On Error GoTo Failed
    If p Is Nothing Then
        wb.CustomDocumentProperties.Add _
            name:=PROP_CONSENT, LinkToContent:=False, _
            Type:=msoPropertyTypeString, value:=choice
    Else
        p.value = choice
    End If
    SCStd_WriteConsent = True
    Exit Function
Failed:
    SCStd_WriteConsent = False
End Function

Private Function SCStd_IsCheckbox(ByVal s As Excel.Shape) As Boolean
    On Error GoTo Done
    If s.Type <> msoFormControl Then Exit Function
    SCStd_IsCheckbox = (s.FormControlType = xlCheckBox)
Done:
End Function

Private Function SCStd_IsEligible(ByVal s As Excel.Shape) As Boolean
    Dim actionName As String
    On Error GoTo Done
    If Not SCStd_IsCheckbox(s) Then Exit Function
    If s.Visible <> msoTrue Then Exit Function
    actionName = Trim$(s.OnAction)
    If Len(actionName) > 0 Then Exit Function
    If s.Width < 12 Or s.Height < 7 Then Exit Function
    SCStd_IsEligible = True
Done:
End Function

Private Function SCStd_CountEligible(ByVal wb As Excel.Workbook) As Long
    Dim ws As Excel.Worksheet
    Dim s As Excel.Shape
    On Error GoTo Done
    For Each ws In wb.Worksheets
        If ws.Visible = xlSheetVisible And _
           Not ws.ProtectDrawingObjects And Not ws.ProtectContents Then
            For Each s In ws.Shapes
                If SCStd_IsEligible(s) Then SCStd_CountEligible = SCStd_CountEligible + 1
            Next s
        End If
    Next ws
Done:
End Function

Private Function SCStd_FindOverlay(ByVal ws As Excel.Worksheet, _
                                  ByVal originalName As String) As Excel.Shape
    Dim i As Long
    Dim textTag As String
    textTag = TAG_CB & originalName
    On Error GoTo Done
    For i = 1 To ws.Shapes.Count
        If ws.Shapes(i).AlternativeText = textTag Then
            Set SCStd_FindOverlay = ws.Shapes(i)
            Exit Function
        End If
    Next i
Done:
End Function

Private Function SCStd_OverlayAction() As String
    SCStd_OverlayAction = "'" & Replace(ThisWorkbook.name, "'", "''") & "'!SCStd_ToggleCheckbox"
End Function

Private Function SCStd_FindBox(ByVal ws As Excel.Worksheet, _
                               ByVal originalName As String) As Excel.Shape
    Dim i As Long
    On Error GoTo Done
    For i = 1 To ws.Shapes.Count
        If ws.Shapes(i).AlternativeText = TAG_BOX & originalName Then
            Set SCStd_FindBox = ws.Shapes(i)
            Exit Function
        End If
    Next i
Done:
End Function

Private Sub SCStd_RenderOverlay(ByVal hit As Excel.Shape, _
                                ByVal box As Excel.Shape, _
                                ByVal original As Excel.Shape)
    ' The ORIGINAL checkbox stays visible: Excel draws its caption unchanged.
    ' The invisible, full-width HIT layer makes the entire label clickable.
    ' The visible small BOX covers only the original checkbox glyph.
    Dim side As Double
    Dim state As Long
    On Error GoTo RenderFail

    side = SC14_MARK_SIZE_PT
    If side > original.Height - 0.5 Then side = original.Height - 0.5
    If side > original.Width - 0.5 Then side = original.Width - 0.5
    If side < 5 Then Err.Raise vbObjectError + 1401, , "Check box too small for 1.4 overlay."
    state = original.ControlFormat.value

    With hit
        .Left = original.Left
        .Top = original.Top
        .Width = original.Width
        .Height = original.Height
        .AlternativeText = TAG_CB & original.name
        .OnAction = SCStd_OverlayAction()
        .Placement = original.Placement
        .Fill.Visible = msoTrue
        .Fill.ForeColor.RGB = RGB(255, 255, 255)
        .Fill.Transparency = 1
        .Line.Visible = msoFalse
        .TextFrame2.TextRange.Text = vbNullString
        .ZOrder msoBringToFront
    End With

    With box
        .Left = original.Left + SC14_MARK_LEFT_PT
        .Top = original.Top + (original.Height - side) / 2 + SC14_MARK_TOP_PT
        .Width = side
        .Height = side
        .AlternativeText = TAG_BOX & original.name
        .OnAction = SCStd_OverlayAction()
        .Placement = original.Placement
        .Fill.Visible = msoTrue
        .Fill.Transparency = 0
        If state = xlOn Then
            .Fill.ForeColor.RGB = RGB(0, 0, 0)
            .Line.Visible = msoTrue
            .Line.ForeColor.RGB = RGB(0, 0, 0)
        Else
            .Fill.ForeColor.RGB = RGB(255, 255, 255)
            .Line.Visible = msoTrue
            .Line.ForeColor.RGB = RGB(0, 0, 0)
        End If
        .Line.Weight = 0.75
        .TextFrame2.TextRange.Text = vbNullString
        .ZOrder msoBringToFront
    End With
    Exit Sub
RenderFail:
    Err.Raise Err.Number, "SCStd_RenderOverlay", Err.Description
End Sub

Private Function SCStd_AddOrUpdateOverlay(ByVal original As Excel.Shape) As Boolean
    Dim ws As Excel.Worksheet
    Dim hit As Excel.Shape
    Dim box As Excel.Shape
    Dim createdHit As Boolean
    Dim createdBox As Boolean

    On Error GoTo Failed
    Set ws = original.Parent
    Set hit = SCStd_FindOverlay(ws, original.name)
    Set box = SCStd_FindBox(ws, original.name)

    ' Upgrade-in-place compatibility: old 1.3 hid the checkbox and used
    ' a full-size text overlay with the same TAG_CB prefix.
    ' Reuse that overlay as a transparent hit area instead.
    If Not hit Is Nothing Then original.Visible = msoTrue
    If Not SCStd_IsEligible(original) Then Exit Function

    If hit Is Nothing Then
        Set hit = ws.Shapes.AddShape(msoShapeRectangle, original.Left, _
                                     original.Top, original.Width, original.Height)
        createdHit = True
        hit.name = "SQSTD_CB_" & CStr(original.ID)
        hit.AlternativeText = TAG_CB & original.name
    End If
    If box Is Nothing Then
        Set box = ws.Shapes.AddShape(msoShapeRectangle, original.Left, _
                                     original.Top, SC14_MARK_SIZE_PT, SC14_MARK_SIZE_PT)
        createdBox = True
        box.name = "SQSTD_BOX_" & CStr(original.ID)
        box.AlternativeText = TAG_BOX & original.name
    End If

    SCStd_RenderOverlay hit, box, original
    ' Intentionally do NOT hide the native control or change its OnAction.
    original.Visible = msoTrue
    SCStd_AddOrUpdateOverlay = True
    Exit Function
Failed:
    On Error Resume Next
    If createdBox Then
        If Not box Is Nothing Then box.Delete
    End If
    If createdHit Then
        If Not hit Is Nothing Then hit.Delete
    End If
    original.Visible = msoTrue
    SCStd_AddOrUpdateOverlay = False
End Function

Public Sub SCStd_ApplySheet(ByVal ws As Excel.Worksheet)
    Dim i As Long
    Dim oldCount As Long
    Dim converted As Long
    Dim s As Excel.Shape
    Dim overlay As Excel.Shape
    Dim oldUpdating As Boolean

    If mBusy Then Exit Sub
    If ws Is Nothing Then Exit Sub
    If ws.Parent Is ThisWorkbook Then Exit Sub
    If ws.Visible <> xlSheetVisible Then Exit Sub
    If ws.ProtectDrawingObjects Or ws.ProtectContents Then Exit Sub
    If SCStd_ReadConsent(ws.Parent) <> PROP_YES Then Exit Sub

    On Error GoTo Finish
    mBusy = True
    oldUpdating = Application.ScreenUpdating
    Application.ScreenUpdating = False
    oldCount = ws.Shapes.Count
    For i = 1 To oldCount
        Set s = ws.Shapes(i)
        If SCStd_IsCheckbox(s) Then
            Set overlay = SCStd_FindOverlay(ws, s.name)
            If Not overlay Is Nothing Or SCStd_IsEligible(s) Then
                If SCStd_AddOrUpdateOverlay(s) Then converted = converted + 1
                If converted >= MAX_PER_SHEET Then Exit For
            End If
        End If
    Next i
Finish:
    Application.ScreenUpdating = oldUpdating
    mBusy = False
End Sub

Public Sub SCStd_ApplyWorkbook(ByVal wb As Excel.Workbook)
    Dim ws As Excel.Worksheet
    If wb Is Nothing Then Exit Sub
    If SCStd_ReadConsent(wb) <> PROP_YES Then Exit Sub
    For Each ws In wb.Worksheets
        SCStd_ApplySheet ws
    Next ws
End Sub

Public Sub SCStd_ToggleCheckbox()
    Dim ws As Excel.Worksheet
    Dim clicked As Excel.Shape
    Dim hit As Excel.Shape
    Dim box As Excel.Shape
    Dim original As Excel.Shape
    Dim callerName As String
    Dim tagText As String
    Dim originalName As String
    Dim activeObj As Object

    If mBusy Then Exit Sub
    On Error GoTo Failed
    Set activeObj = Application.ActiveSheet
    If activeObj Is Nothing Then Exit Sub
    If Not TypeOf activeObj Is Excel.Worksheet Then Exit Sub
    Set ws = activeObj
    If SCStd_ReadConsent(ws.Parent) <> PROP_YES Then Exit Sub
    If ws.ProtectContents Then Exit Sub
    callerName = CStr(Application.Caller)
    Set clicked = ws.Shapes(callerName)
    tagText = clicked.AlternativeText
    If Left$(tagText, Len(TAG_CB)) = TAG_CB Then
        originalName = Mid$(tagText, Len(TAG_CB) + 1)
    ElseIf Left$(tagText, Len(TAG_BOX)) = TAG_BOX Then
        originalName = Mid$(tagText, Len(TAG_BOX) + 1)
    Else
        Exit Sub
    End If
    Set original = ws.Shapes(originalName)
    If Not SCStd_IsCheckbox(original) Then Exit Sub
    Set hit = SCStd_FindOverlay(ws, originalName)
    Set box = SCStd_FindBox(ws, originalName)
    If hit Is Nothing Or box Is Nothing Then Exit Sub

    mBusy = True
    If original.ControlFormat.value = xlOn Then
        original.ControlFormat.value = xlOff
    Else
        original.ControlFormat.value = xlOn
    End If
    SCStd_RenderOverlay hit, box, original
    mBusy = False
    Exit Sub
Failed:
    mBusy = False
    MsgBox "切替処理に失敗しました。" & vbCrLf & Err.Description, _
           vbExclamation, "SquareClick Standard 1.4 TEST"
End Sub

Public Sub SCStd_RefreshActiveWorkbook()
    Dim wb As Excel.Workbook
    On Error GoTo Failed
    Set wb = Application.ActiveWorkbook
    If wb Is Nothing Then Exit Sub
    If SCStd_ReadConsent(wb) = PROP_YES Then
        SCStd_ApplyWorkbook wb
        MsgBox "チェックボックス表示を更新しました。", vbInformation, "SquareClick Standard"
    Else
        MsgBox "このブックではまだ標準表示が有効ではありません。", vbInformation, "SquareClick Standard"
    End If
    Exit Sub
Failed:
    MsgBox "更新に失敗しました。" & vbCrLf & Err.Description, vbExclamation
End Sub

Public Function SCStd_ChangeMode(ByVal wb As Excel.Workbook, _
                                   ByVal modeValue As String) As Boolean
    ' Shared by the Ribbon settings dialog and initial No confirmation.
    ' A failed cleanup MUST NOT mark the book as disabled.
    Dim ws As Excel.Worksheet
    Dim currentSheet As Object
    Dim details As String
    If mBusy Then
        ' Called from initial No confirmation only after prompt guard cleared.
        Exit Function
    End If
    If wb Is Nothing Then Exit Function
    If wb Is ThisWorkbook Then Exit Function
    If wb.ReadOnly Then
        MsgBox "読み取り専用のブックです。設定は保存できません。", _
               vbExclamation, "SquareClick"
        Exit Function
    End If
    If modeValue <> PROP_YES And modeValue <> PROP_NO Then Exit Function

    On Error GoTo Failed
    mBusy = True
    If modeValue = PROP_NO Then
        ' Remove all runtime shapes; keep cell values and checkbox states.
        For Each ws In wb.Worksheets
            If Not SCStd_CleanSheet(ws) Then
                details = "チェックボックス表示を戻せませんでした: " & ws.name
                GoTo Failed
            End If
            If Not SquareClickCore.SquareClick_CleanSheet(ws) Then
                details = "入力規則のクリック領域を除去できませんでした: " & ws.name
                GoTo Failed
            End If
        Next ws
    End If

    If Not SCStd_WriteConsent(wb, modeValue) Then
        details = "ブックの設定情報を書き込めませんでした。"
        GoTo Failed
    End If
    mBusy = False
    If modeValue = PROP_YES Then
        SCStd_ApplyWorkbook wb
        Set currentSheet = wb.ActiveSheet
        If Not currentSheet Is Nothing Then
            If TypeOf currentSheet Is Excel.Worksheet Then
                SquareClickCore.SquareClick_PrepareSheet currentSheet
            End If
        End If
    End If
    SCStd_ChangeMode = True
    Exit Function

Failed:
    mBusy = False
    If Len(details) = 0 Then details = Err.Description
    MsgBox "SquareClickの設定変更を完了できませんでした。" & vbCrLf & _
           details & vbCrLf & _
           "元のファイルを保存する前に状態をご確認ください。", _
           vbExclamation, "SquareClick"
End Function

Public Sub SCStd_ShowSettingsForActiveWorkbook()
    Dim wb As Excel.Workbook
    Dim dlg As SCStdSettings
    Dim chosen As String
    Dim doApply As Boolean
    Dim current As String

    On Error GoTo Failed
    Set wb = Application.ActiveWorkbook
    If wb Is Nothing Or wb Is ThisWorkbook Then
        MsgBox "設定するExcelブックを開いてください。", vbInformation, "SquareClick"
        Exit Sub
    End If
    If SquareClickSession.SCSession_IsBusy Then
        MsgBox "保存処理が完了してから操作してください。", vbExclamation, "SquareClick"
        Exit Sub
    End If
    If wb.ReadOnly Then
        MsgBox "読み取り専用のため、設定を変更できません。", vbInformation, "SquareClick"
        Exit Sub
    End If

    current = SCStd_ReadConsent(wb)
    Set dlg = New SCStdSettings
    dlg.InitFor wb
    dlg.Show vbModal
    doApply = dlg.Confirmed
    chosen = dlg.SelectedMode
    Unload dlg
    Set dlg = Nothing
    If Not doApply Then Exit Sub
    If chosen <> PROP_YES And chosen <> PROP_NO Then Exit Sub

    If chosen = current Then
        MsgBox "現在の設定から変更はありません。", vbInformation, "SquareClick"
        Exit Sub
    End If
    If Not SCStd_ChangeMode(wb, chosen) Then Exit Sub

    If chosen = PROP_YES Then
        MsgBox "この文書でSquareClickを有効にしました。" & vbCrLf & _
               "設定を次回も使用するには、この文書を保存してください。", _
               vbInformation, "SquareClick"
    Else
        MsgBox "この文書でSquareClickを無効にしました。" & vbCrLf & _
               "設定を次回も使用するには、この文書を保存してください。", _
               vbInformation, "SquareClick"
    End If
    Exit Sub
Failed:
    On Error Resume Next
    If Not dlg Is Nothing Then Unload dlg
    MsgBox "設定画面でエラーが発生しました: " & Err.Description, _
           vbExclamation, "SquareClick"
End Sub

Public Sub SCStd_EnableActiveWorkbook()
    ' Compatibility entry point: open the same Ribbon settings dialog.
    SCStd_ShowSettingsForActiveWorkbook
End Sub

Public Sub SCStd_RestoreActiveWorkbook()
    ' Compatibility entry point: open the same Ribbon settings dialog.
    SCStd_ShowSettingsForActiveWorkbook
End Sub

' Book closure cleanup only; does not save, modify, cancel or print the workbook.
Public Sub SCStd_ForgetSession(ByVal wb As Excel.Workbook)
    Dim i As Long
    Dim item As Excel.Workbook
    If mDeferredWorkbooks Is Nothing Then Exit Sub
    For i = mDeferredWorkbooks.Count To 1 Step -1
        Set item = mDeferredWorkbooks.item(i)
        If item Is wb Then
            mDeferredWorkbooks.Remove i
        End If
    Next i
End Sub

' Restores native controls and removes only SquareClick temporary UI shapes.
' Save cleanup removes both click area and square; on-disk controls stay native.
Public Function SCStd_CleanSheet(ByVal ws As Excel.Worksheet) As Boolean
    ' Restore native checkbox visibility; remove BOTH temporary overlay shapes.
    ' Retain the original control, caption, state, link-cell, and OnAction.
    Dim i As Long
    Dim overlay As Excel.Shape
    Dim original As Excel.Shape
    Dim originalName As String
    Dim tag As String
    On Error GoTo Fail
    SCStd_CleanSheet = False
    If ws Is Nothing Then Exit Function
    For i = ws.Shapes.Count To 1 Step -1
        Set overlay = ws.Shapes(i)
        tag = overlay.AlternativeText
        originalName = vbNullString
        If Left$(tag, Len(TAG_CB)) = TAG_CB Then
            originalName = Mid$(tag, Len(TAG_CB) + 1)
        ElseIf Left$(tag, Len(TAG_BOX)) = TAG_BOX Then
            originalName = Mid$(tag, Len(TAG_BOX) + 1)
        End If
        If Len(originalName) > 0 Then
            Set original = Nothing
            On Error Resume Next
            Set original = ws.Shapes(originalName)
            On Error GoTo Fail
            If Not original Is Nothing Then
                If Not SCStd_IsCheckbox(original) Then GoTo Fail
                original.Visible = msoTrue
            End If
            overlay.Delete
        End If
    Next i
    SCStd_CleanSheet = True
    Exit Function
Fail:
    SCStd_CleanSheet = False
End Function
