private async Task <MultiTablePreview> GeneratePreview()
        {
            var metas      = _xlsSheetMetas.Where(x => x.ToBeImported).ToList();
            var tableNames = metas.Select(m => m.NewName).ToList();

            // build the sql string
            var prefix = Guid.NewGuid().ToString().Replace("-", "") + "_";
            var sb     = new StringBuilder(GetImportSql(prefix));

            sb.AppendLine();
            foreach (var m in metas)
            {
                sb.AppendLine($"SELECT * FROM {(prefix + m.NewName).DoubleQuote()} LIMIT 1000;");
                sb.AppendLine($"DROP TABLE {(prefix + m.NewName).DoubleQuote()};");
            }
            var sql = sb.ToString();

            // run it in a transaction and then roll it back so nothing is actually affected
            var output = await Task.Run(() =>
                                        _manager.ExecuteScriptEx(
                                            code: sql,
                                            args: new Dictionary <string, object>(),
                                            transactionType: NotebookManager.TransactionType.RollbackTransaction,
                                            vars: out _));

            if (output.DataTables.Count != metas.Count)
            {
                // this shouldn't happen, it should have thrown from ExecuteScriptEx
                throw new Exception("The import failed to generate all the tables.");
            }

            // read out the contents of each table, which we arranged to have selected in our script
            return(new MultiTablePreview {
                Tables = metas.Select((x, i) => (TableName: x.NewName, DataTable: output.DataTables[i])).ToList()
            });