Code:
 on *:start:{
  if !$hget(Blacklist) { .hmake Blacklist 100 }
  if $exists(Blacklist.hsh) { .hload Blacklist Blacklist.hsh }
}
on *:exit:{
  .hsave -o Blacklist Blacklist.hsh
}
on *:disconnect:{
  .hsave -o Blacklist Blacklist.hsh
}
on !*:join:#:{
  if $hget(Blacklist,$nick) {
    echo -a Blacklisted $nick has joined $chan
    if $me isop $chan {
      .ban -k $chan $nick 2 $hget(Blacklist,$nick) Kick $chr(35) $hget(Blacklist,$+(Count,.,$nick))
    }
  }
}
on *:op:#:{
  blacklist scan $chan
}
on *:serverop:#:{
  blacklist scan $chan
}
on *:ban:#:{
  if $nick = $me {
    .ignore $bmask
  }
}
on *:kick:#:{
  if $nick == $me {
    hinc Blacklist $+(Count,.,$knick))
  }
  updatenl
}
alias blacklist {
  if $1 == add {
    set %reason $gettok($2-,1--1,32)
    set %nicks $gettok($2-,-1,32)
    if %nicks == $2- {
      set %nicks $$?="Nick(s) to be added to blacklist"
    }
    set %nicks $replace(%nicks,$chr(44),$chr(32))
    var %a = 1, %b = $numtok(%nicks,32)
    while %a <= %b {
      .hadd -m Blacklist $gettok(%nicks,%a,32) $iif(%reason,$v1,$$?="Blacklist Reason")
      inc %a
    }
  }
  elseif $1 == del {
    set %nicks $2-
    set %nicks $replace(%nicks,$chr(44),$chr(32))
    var %a = 1, %b = $numtok(%nicks,32)
    while %a <= %b {
      .hdel Blacklist $gettok(%nicks,%a,32)
      inc %a
    }
  }
  elseif $1 == scan {
    if $me isop $2 {
      var %a = 1
      while %a <= $nick($2,0) {
        if $hget(Blacklist,$nick($2,%a)) {
          .ban -k $1 $nick($2,%a) 2 $hget(Blacklist,$nick($2,%a)) Kick $chr(35) $hget(Blacklist,$+(Count,.,$nick($2,%a)))
          dec %a
        }
        inc %a
      }
    }
  }
}
menu query {
  Blacklist Reason : .hadd -m Blacklist $nick $$?="Reason"
}
menu channel,nicklist,status {
  Blacklist
  .PM Spammer : blacklist add PM Spammer $snicks 
  .Flooder : blacklist add Flooder $snicks
  .Custom : blacklist add $?="Common Reason" $snicks 
  ; If common reason isn't included, you will be asked for a reason for each nick
}
menu channel,status {
  Blacklist
  .Remove : blacklist del $$?="Name(s) to be removed"
}
 


I think that should be a final code. I did test it briefly, and all of the noted problems have been resolved.

Also, in the areas where you are asked for nick(s)/name(s), the code has been set to accept multiple entries, with the entries being separated by either space or comma.