This method imports a Pandas Data Frame to a SAS Data Set, returning the SASdata object for the new Data Set.
      df      - Pandas Data Frame to import to a SAS Data Set
      table   - the name of the SAS Data Set to create
      libref  - the libref for the SAS Data Set being created. Defaults to WORK, or USER if assigned
      keep_outer_quotes - for character columns, have SAS keep any outer quotes instead of stripping them off.

def dataframe2sasdata(self, df: '<Pandas Data Frame object>', table: str ='a', 
                         libref: str ="", keep_outer_quotes: bool=False):
      """
      This method imports a Pandas Data Frame to a SAS Data Set, returning the SASdata object for the new Data Set.
      df      - Pandas Data Frame to import to a SAS Data Set
      table   - the name of the SAS Data Set to create
      libref  - the libref for the SAS Data Set being created. Defaults to WORK, or USER if assigned
      keep_outer_quotes - for character columns, have SAS keep any outer quotes instead of stripping them off.
      """
      input  = ""
      card   = ""
      format = ""
      length = ""
      dts    = []
      ncols  = len(df.columns)

      for name in range(ncols):
         input += "'"+str(df.columns[name])+"'n "
         if df.dtypes[df.columns[name]].kind in ('O','S','U','V'):
            try:
               col_l = df[df.columns[name]].astype(str).apply(self._getbytelen).max()
            except Exception as e:
               print("Transcoding error encountered.")
               print("DataFrame contains characters that can't be transcoded into the SAS session encoding.\n"+str(e))
               return None
            if col_l == 0:
               col_l = 8
            length += " '"+str(df.columns[name])+"'n $"+str(col_l)
            if keep_outer_quotes:
               input  += "~ "
            dts.append('C')
         else:
            if df.dtypes[df.columns[name]].kind in ('M'):
               length += " '"+str(df.columns[name])+"'n 8"
               input  += ":E8601DT26.6 "
               format += "'"+str(df.columns[name])+"'n E8601DT26.6 "
               dts.append('D')
            else:
               length += " '"+str(df.columns[name])+"'n 8"
               if df.dtypes[df.columns[name]] == 'bool':
                  dts.append('B')
               else:
                  dts.append('N')

      code = "data "
      if len(libref):
         code += libref+"."
      code += table+";\n"
      if len(length):
         code += "length "+length+";\n"
      if len(format):
         code += "format "+format+";\n"
      code += "infile datalines delimiter='03'x DSD STOPOVER;\ninput @;\nif _infile_ = '' then delete;\ninput "+input+";\ndatalines4;"
      self._asubmit(code, "text")

      code = ""
      for row in df.itertuples(index=False):
         card  = ""
         for col in range(ncols):
            var = str(row[col])

            if   dts[col] == 'N' and var == 'nan':
               var = '.'
            elif dts[col] == 'C' and var == 'nan':
               var = ' '
            elif dts[col] == 'B':
               var = str(int(row[col]))
            elif dts[col] == 'D':
               if var == 'nan':
                  var = '.'
               else:
                  var = str(row[col].to_datetime64())[:26]

            card += var
            if col < (ncols-1):
               card += chr(3)
         code += card+"\n"
         if len(code) > 4000:
            self._asubmit(code, "text")
            code = ""

      self._asubmit(code+";;;;", "text")
      ll = self.submit("run;", 'text')
      return