Avatar billede chrisrj Forsker
15. februar 2023 - 15:11 Der er 12 kommentarer

Importere mange forskellige dataer fra excel ark

Hejsa

Jeg skal importere mange forskellige dataer fra mange regneark.

Data står i  "grupper" på hvert ark.

Det skal alt sammen ned i samme tabel i db'en, men:

1) En del af Kolonneoverskrifterne variere.
2) Der er både vandrette og lodrette kolonneoverskrifter
3) Nogle af de vandrette er i to lag (altså grupperet)
4) Grupperne står ikke samme sted eller har samme størrelse (gælder både rækker og kolonner)


Findes der er "nem" måde at importere det på, eller er jeg nødt til at gøre "semi-manuelt"?

Semi-manuelt betyder her, at jeg kopiere data-grupper over i tomme ark og tilretter overskrifter manuelt, og kører derefter importfunktion.
Avatar billede arne_v Ekspert
15. februar 2023 - 15:19 #1
Nu har du spurgt i C# kategorien.

Så hvad med at skrive et C# program som læser fra regnearkene og indsætter i databasen.

Særdeles manuelt, men fuld fleksibilitet.
Avatar billede arne_v Ekspert
15. februar 2023 - 15:20 #2
Og for en god ordens skyld: jeg foreslå at læse regneark med OLE DB / ODBC ikke med Excel komponent.
Avatar billede chrisrj Forsker
15. februar 2023 - 15:28 #3
Det er helt bevist at jeg har lagt spg. her. :)

Og det er netop c# kode jeg er på jagt efter. :)

Kode til at gøre det Manuelt har jeg, det kommer bare til at tage MEGA lang tid at importere det hele med den kode. :-/

Så derfor spørgsmålet om det kan gøres nemmere. ;)
Avatar billede arne_v Ekspert
15. februar 2023 - 15:34 #4
OK.

Hvad er problemet?

Kører programmet langsomt?

Eller er problemet at det tager dage/uger at skrive den kode som som henter dataene fordi layout er så forskellig?
Avatar billede chrisrj Forsker
15. februar 2023 - 15:40 #5
Det er det sidste.

Jeg har dog fundet ud af, at man kan finde grupperne ved at søge (igen, manuelt her. Jeg fandt 107...) på et ord - hvis det er en hjælp?
Avatar billede arne_v Ekspert
15. februar 2023 - 15:54 #6
Svært at sige udfra en kort beskivelse på dansk.

Men jeg får associationer i retning af logik som:

while more data {
    read row
    if row contains all text {
          process row as column headers
    }
    else if row contains text + text + N numbers {
          process as group row header + row header + data
    }
    else if row contains blank + text + N numbers {
          process as row header + data and assume group header same as for last row
    }
}
Avatar billede chrisrj Forsker
15. februar 2023 - 16:16 #7
Hmmm, grupper kan se sådan ud:
https://paste.pics/202c12f968b5b41102d1d1b9a51f863e

Det er "kolonne1" navnet jeg kan søge på, og det ser ud til at det altid står i B kolonnen.
Avatar billede chrisrj Forsker
15. februar 2023 - 16:18 #8
Og der er ikke altid en "gruppe" overskrift (altså gruppe1/gruppe2 ovs) - ligesom at der kan være flere end 2 af dem.
Avatar billede arne_v Ekspert
15. februar 2023 - 16:38 #9
Jeg tror ikke at det er helt nemt, men det må være muligt.

Jeg kan prøve at bixe noget C# som outlinet i #6. Men jeg ved ikke hvornår jeg vil have tid.
Avatar billede chrisrj Forsker
15. februar 2023 - 16:46 #10
Nej, det er jo det! :D Ja, ikke. :)

Heh, jeg prøvede at smide din pseudokode ind i chatgpt. ;P

Den gav følgende:
using System;
using System.Data.OleDb;

namespace ExcelDataReader
{
    class Program
    {
        static void Main(string[] args)
        {
            // Set the path to your Excel file
            string excelFilePath = @"C:\example.xlsx";

            // Set the name of the worksheet you want to extract data from
            string worksheetName = "Sheet1$";

            // Set up the OleDb connection string
            string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excelFilePath + ";Extended Properties='Excel 12.0 Xml;HDR=YES;'";

            // Open the connection to the Excel file using OleDb
            using (OleDbConnection connection = new OleDbConnection(connectionString))
            {
                connection.Open();

                // Set up the OleDb command to select data from the worksheet
                OleDbCommand command = new OleDbCommand("SELECT * FROM [" + worksheetName + "]", connection);

                // Execute the command and read the data using an OleDbDataReader
                using (OleDbDataReader reader = command.ExecuteReader())
                {
                    // Read each row in the worksheet
                    while (reader.Read())
                    {
                        // Check if the row contains all text
                        bool isColumnHeadersRow = true;
                        for (int i = 0; i < reader.FieldCount; i++)
                        {
                            if (reader[i] == DBNull.Value || !(reader[i] is string))
                            {
                                isColumnHeadersRow = false;
                                break;
                            }
                        }

                        if (isColumnHeadersRow)
                        {
                            // Process the row as column headers
                            // TODO: Replace this with your own code to process column headers
                            Console.WriteLine("Processing column headers row");
                        }
                        else
                        {
                            // Check if the row contains text + text + N numbers
                            bool isGroupRowHeaderRow = false;
                            int groupRowHeaderCount = 0;
                            for (int i = 0; i < reader.FieldCount; i++)
                            {
                                if (reader[i] == DBNull.Value)
                                {
                                    break;
                                }
                                else if (i < 2 && reader[i] is string)
                                {
                                    // First two columns must be text
                                    isGroupRowHeaderRow = true;
                                }
                                else if (i >= 2 && reader[i] is double)
                                {
                                    // Remaining columns must be numbers
                                    groupRowHeaderCount++;
                                }
                                else
                                {
                                    // If any column does not match the pattern, this is not a group row header row
                                    isGroupRowHeaderRow = false;
                                    break;
                                }
                            }

                            if (isGroupRowHeaderRow)
                            {
                                // Process the row as group row header + row header + data
                                // TODO: Replace this with your own code to process group row header + row header + data
                                Console.WriteLine("Processing group row header + row header + data row");
                            }
                            else
                            {
                                // Check if the row contains blank + text + N numbers
                                bool isDataRow = false;
                                int dataCount = 0;
                                for (int i = 0; i < reader.FieldCount; i++)
                                {
                                    if (reader[i] == DBNull.Value)
                                    {
                                        isDataRow = true;
                                    }
                                    else if (isDataRow && i == 1 && reader[i] is string)
                                    {
                                        // Second column must be text
                                    }
                                    else if (isDataRow && i >= 2 && reader[i] is double)
                                    {
                                        // Remaining columns must be numbers
                                        dataCount++;
                                    }
                                    else
                                    {
                                        // If any column does not match the pattern, this is not a data row
                                        isDataRow = false;
                                        break;
                                    }
                                }

                                if (isDataRow)
                                {
                                    // Process the row as row header + data and assume group header same as for last row
                                    // TODO: Replace this with your own code to process row header + data and assume group header same as for last row
                                    Console.WriteLine("Processing row header + data row");
                                }
                                else
                                {
                                    // Row does not match any pattern, skip it
                                }
                            }
                        }
                    }
                }
            }

            Console.WriteLine("Done");
            Console.ReadLine();
        }
    }
}
Avatar billede arne_v Ekspert
01. marts 2023 - 19:27 #11
Det tog lidt tid men jeg har leget lidt med det.

Og jeg endte med at dele det lidt op i.s.f. at forsøge at lave alt i et gennemløb.

Kode:


using System;
using System.Collections.Generic;
using System.Data.OleDb;
using System.Linq;

namespace ExcelEater
{
    public class Program
    {
        public static void StripEmptyRows(List<List<string>> data)
        {
            for(int rownum = data.Count - 1; rownum >= 0; rownum--)
            {
                if(data[rownum].All(val => val == ""))
                {
                    data.RemoveAt(rownum);
                }
            }
        }
        public static void StripEmptyCols(List<List<string>> data)
        {
            for(int colnum = data[0].Count - 1; colnum >=0; colnum--)
            {
                if(Enumerable.Range(0, data.Count - 1).All(rownum => data[rownum][colnum] == ""))
                {
                    foreach(List<string> row in data)
                    {
                        row.RemoveAt(colnum);
                    }
                }
            }
        }
        public static void Crop(List<List<string>> data)
        {
            StripEmptyRows(data);
            StripEmptyCols(data);
        }
        public static int TopHeaderRows(List<List<string>> data)
        {
            int res = 0;
            while(res < data.Count && data[res].All(val => val == "" || char.IsLetter(val[0])))
            {
                res++;
            }
            return res;
        }
        public static int LeftHeaderCols(List<List<string>> data)
        {
            int res = 0;
            while(res < data[0].Count && Enumerable.Range(0, data.Count).All(rownum => data[rownum][res] == "" || char.IsLetter(data[rownum][res][0])))
            {
                res++;               
            }
            return res;           
        }
        public static void FillRows(List<List<string>> data, int nrowhdr, int ncolhdr)
        {
            for(int rownum = 0; rownum < nrowhdr; rownum++)
            {
                string last = "";
                for(int colnum = ncolhdr; colnum < data[rownum].Count; colnum++)
                {
                    if(data[rownum][colnum] == "")
                    {
                        data[rownum][colnum] = last;
                    }
                    last = data[rownum][colnum];
                }
            }
        }
        public static void FillCols(List<List<string>> data, int nrowhdr, int ncolhdr)
        {
            for(int colnum = 0; colnum < ncolhdr; colnum++)
            {
                string last = "";
                for(int rownum = nrowhdr; rownum < data.Count; rownum++)
                {
                    if(data[rownum][colnum] == "")
                    {
                        data[rownum][colnum] = last;
                    }
                    last = data[rownum][colnum];
                }
            }
        }
        public static void Fill(List<List<string>> data, int nrowhdr, int ncolhdr)
        {
            FillRows(data, nrowhdr, ncolhdr);
            FillCols(data, nrowhdr, ncolhdr);
        }
        public static void Process(List<List<string>> data, int nrowhdr, int ncolhdr, Action<List<string>, List<string>, string> proc)
        {
            for(int rownum = nrowhdr; rownum < data.Count; rownum++)
            {
                for(int colnum = ncolhdr; colnum < data[rownum].Count; colnum++)
                {
                    proc(data[rownum].Take(ncolhdr).ToList(), Enumerable.Range(0, nrowhdr).Select(rn => data[rn][colnum]).ToList(), data[rownum][colnum]);
                }
            }
        }
        public static List<List<string>> Load(string fnm)
        {
            List<List<string>> res = new List<List<string>>();
            using(OleDbConnection con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fnm + ";Extended Properties=\"Excel 12.0 Xml;HDR=NO;IMEX=1\";" ))
            {
                con.Open();
                using(OleDbCommand cmd = con.CreateCommand())
                {
                    cmd.CommandText = "SELECT * FROM [Sheet1$]";
                    cmd.Connection = con;
                    using(OleDbDataReader rdr = cmd.ExecuteReader())
                    {
                        while(rdr.Read())
                        {
                            List<string> row = new List<string>();
                            for(int fldnum = 0; fldnum < rdr.FieldCount; fldnum++)
                            {
                                row.Add(rdr.GetValue(fldnum).ToString());
                            }
                            res.Add(row);
                        }
                    }
                }
            }
            return res;
        }
        public static void Dump(string label, List<List<string>> data)
        {
            Console.WriteLine("{0}:", label);
            foreach(List<string> row in data)
            {
                foreach(string val in row)
                {
                    Console.Write("{0,5}", val);
                }
                Console.WriteLine();
            }
        }
        public static void Main(string[] args)
        {
            List<List<string>> data = Load(@"C:\Work\skel.xlsx");
            Dump("After Load", data);
            Crop(data);
            Dump("After Crop", data);
            int nrowhdr = TopHeaderRows(data);
            int ncolhdr = LeftHeaderCols(data);
            Fill(data, nrowhdr, ncolhdr);
            Dump("After Fill", data);
            Process(data, nrowhdr, ncolhdr, (rowhdrs,colhdrs,val) => { Console.WriteLine("({0}) ({1}) : {2}", string.Join(",", rowhdrs), string.Join(",", colhdrs),val); });
            Console.ReadKey();
        }
    }
}


Output fra mit eksempel:


After Load:
                  c1                  c2
                c11      c12      c21      c22
                c111 c112 c121 c122 c211 c212 c221 c222
  r1  r11 r111    1    2    3    4    5    6    7    8
          r112    9  10  11  12  13  14  15  16
      r12 r121  17  18  19  20  21  22  23  24
          r122  25  26  27  28  29  30  31  32
  r2  r21 r211  33  34  35  36  37  38  39  40
          r212  41  42  43  44  45  46  47  48
      r22 r221  49  50  51  52  53  54  55  56
          r222  57  58  59  60  61  62  63  64
After Crop:
                  c1                  c2
                c11      c12      c21      c22
                c111 c112 c121 c122 c211 c212 c221 c222
  r1  r11 r111    1    2    3    4    5    6    7    8
          r112    9  10  11  12  13  14  15  16
      r12 r121  17  18  19  20  21  22  23  24
          r122  25  26  27  28  29  30  31  32
  r2  r21 r211  33  34  35  36  37  38  39  40
          r212  41  42  43  44  45  46  47  48
      r22 r221  49  50  51  52  53  54  55  56
          r222  57  58  59  60  61  62  63  64
After Fill:
                  c1  c1  c1  c1  c2  c2  c2  c2
                c11  c11  c12  c12  c21  c21  c22  c22
                c111 c112 c121 c122 c211 c212 c221 c222
  r1  r11 r111    1    2    3    4    5    6    7    8
  r1  r11 r112    9  10  11  12  13  14  15  16
  r1  r12 r121  17  18  19  20  21  22  23  24
  r1  r12 r122  25  26  27  28  29  30  31  32
  r2  r21 r211  33  34  35  36  37  38  39  40
  r2  r21 r212  41  42  43  44  45  46  47  48
  r2  r22 r221  49  50  51  52  53  54  55  56
  r2  r22 r222  57  58  59  60  61  62  63  64
(r1,r11,r111) (c1,c11,c111) : 1
(r1,r11,r111) (c1,c11,c112) : 2
(r1,r11,r111) (c1,c12,c121) : 3
(r1,r11,r111) (c1,c12,c122) : 4
(r1,r11,r111) (c2,c21,c211) : 5
(r1,r11,r111) (c2,c21,c212) : 6
(r1,r11,r111) (c2,c22,c221) : 7
(r1,r11,r111) (c2,c22,c222) : 8
(r1,r11,r112) (c1,c11,c111) : 9
(r1,r11,r112) (c1,c11,c112) : 10
(r1,r11,r112) (c1,c12,c121) : 11
(r1,r11,r112) (c1,c12,c122) : 12
(r1,r11,r112) (c2,c21,c211) : 13
(r1,r11,r112) (c2,c21,c212) : 14
(r1,r11,r112) (c2,c22,c221) : 15
(r1,r11,r112) (c2,c22,c222) : 16
(r1,r12,r121) (c1,c11,c111) : 17
(r1,r12,r121) (c1,c11,c112) : 18
(r1,r12,r121) (c1,c12,c121) : 19
(r1,r12,r121) (c1,c12,c122) : 20
(r1,r12,r121) (c2,c21,c211) : 21
(r1,r12,r121) (c2,c21,c212) : 22
(r1,r12,r121) (c2,c22,c221) : 23
(r1,r12,r121) (c2,c22,c222) : 24
(r1,r12,r122) (c1,c11,c111) : 25
(r1,r12,r122) (c1,c11,c112) : 26
(r1,r12,r122) (c1,c12,c121) : 27
(r1,r12,r122) (c1,c12,c122) : 28
(r1,r12,r122) (c2,c21,c211) : 29
(r1,r12,r122) (c2,c21,c212) : 30
(r1,r12,r122) (c2,c22,c221) : 31
(r1,r12,r122) (c2,c22,c222) : 32
(r2,r21,r211) (c1,c11,c111) : 33
(r2,r21,r211) (c1,c11,c112) : 34
(r2,r21,r211) (c1,c12,c121) : 35
(r2,r21,r211) (c1,c12,c122) : 36
(r2,r21,r211) (c2,c21,c211) : 37
(r2,r21,r211) (c2,c21,c212) : 38
(r2,r21,r211) (c2,c22,c221) : 39
(r2,r21,r211) (c2,c22,c222) : 40
(r2,r21,r212) (c1,c11,c111) : 41
(r2,r21,r212) (c1,c11,c112) : 42
(r2,r21,r212) (c1,c12,c121) : 43
(r2,r21,r212) (c1,c12,c122) : 44
(r2,r21,r212) (c2,c21,c211) : 45
(r2,r21,r212) (c2,c21,c212) : 46
(r2,r21,r212) (c2,c22,c221) : 47
(r2,r21,r212) (c2,c22,c222) : 48
(r2,r22,r221) (c1,c11,c111) : 49
(r2,r22,r221) (c1,c11,c112) : 50
(r2,r22,r221) (c1,c12,c121) : 51
(r2,r22,r221) (c1,c12,c122) : 52
(r2,r22,r221) (c2,c21,c211) : 53
(r2,r22,r221) (c2,c21,c212) : 54
(r2,r22,r221) (c2,c22,c221) : 55
(r2,r22,r221) (c2,c22,c222) : 56
(r2,r22,r222) (c1,c11,c111) : 57
(r2,r22,r222) (c1,c11,c112) : 58
(r2,r22,r222) (c1,c12,c121) : 59
(r2,r22,r222) (c1,c12,c122) : 60
(r2,r22,r222) (c2,c21,c211) : 61
(r2,r22,r222) (c2,c21,c212) : 62
(r2,r22,r222) (c2,c22,c221) : 63
(r2,r22,r222) (c2,c22,c222) : 64
Avatar billede chrisrj Forsker
03. marts 2023 - 18:42 #12
Heh, jeg var også lige ved at tro du havde glemt mig. :D

Det ser interessant ud! :) Jeg håber jeg får lov til at teste det af i næste uge. :)

*krydser fingre*
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester