Loading...

Във форума е въведено ограничение, което позволява на потребителите единствено да разглеждат публикуваните въпроси.

Kimanov avatar Kimanov 0 Точки

Връзка на Excel (таблица от xlsx файл) към база на SQL Server

Здравейте!

От известно време се боря с този проблем, на който решаването му с Access е детска игра.

За какво става дума.

Имам данни от таблица в EXCEL, които искам да вкарам в база данни, да ги обработя там с наличната от базата информация и да върна резултата отново в Ексел. Ако говорим за връзка Excel - Access - Excel, това е повече от лесно. Създава се линк в аксеската база към екселската таблица и след като тя се позиционира като част от базата с данни, обработва се с комбинирана заявка и резултатът се връща в същия екселски файл, но в друга таблица.

До момента не съм открил аналогичен вариант с Excel - SQL Server - Excel. Има вариант за създаване на селект заявка или VIEW в SQL Server. Макар на пръв поглед елементарно, това въобще не е просто, с оглед на купчината настройки, задължителното отваряне на SQL Server Management Studio като админ и кръпката AccessDatabaseEngine, която трябва да се инсталира. Човек би подскочил кеф, когато види, че това е сработило. Обаче не! Ако екселският файл е отворен, заявката или View-то връщат грешка:

 Msg 7399, Level 16, State 1, Procedure (Име на View-то), Line 3
The OLE DB provider "Microsoft.ACE.OLEDB.12.0" for linked server "(null)" reported an error. The provider did not give any information about the error.
Msg 7303, Level 16, State 1, Procedure (Име на View-то), Line 3
Cannot initialize the data source object of OLE DB provider "Microsoft.ACE.OLEDB.12.0" for linked server "(null)".

Подобна заявка губи смисъла си, дори ако се потърси вариант за обработка в SQL Server след затваряне на Ексел. Когато отново отвориш Ексел, заявката или view-то гърмят. Когато вместо SQL Server седи Аксес, достатъчно е да поискаш от екселския файл да се ъпдейтне, без дори да се налага да се отваря Аксес. Всичко работи.

Някой да се е сблъсквал с подобен проблем? Ще съм благодарен на всеки, който подскаже някаква идея.

Заявката (view-то), която ползвам в SQL Server са от тип:

SELECT *
FROM OPENROWSET ('Microsoft.ACE.OLEDB.12.0',
    'Excel 12.0 Xml;HDR=YES;
    Database=D:\xxx\SQL\Моят файл.xlsx',
    'SELECT * FROM [Моята таблица$]')

или

SELECT <имената на колоните>
FROM OPENDATASOURCE ('Microsoft.ACE.OLEDB.12.0', 
        'Data Source="D:\xxx\SQL\Моят файл.xlsx"; 
        Extended properties=Excel 12.0' )...[Моята таблица$]

Тагове:
0
Общи приказки
yavor2000 avatar yavor2000 114 Точки

Не е точно по твоя въпрос, но се сблъсках с нещо подобно за изпита ни по ASP.NET MVC. Там трябва да напълним базата (code first) с примерни данни. Когато данните са малко могат да се 'хардкодват' в seed метода, но ако примерните данни са няколко стотин, вече не е ок. Така че потърсих в мрежата и ето какво открих:
https://github.com/dpaquette/SeedingDatabaseFromCSV

Поддържат се custom mappings.Така например тази таблица:

public class Photograph
    {
        public Photograph()
        {
            this.Albums = new HashSet&amp;amp;lt;Album&amp;amp;gt;();
            this.UploadDate = DateTime.Now;
        }

        [Key]
        public int Id { get; set; }

        [Required]
        [StringLength(GlobalConstants.TitleMaxLength), MinLength(GlobalConstants.TitleMinLength)]
        public string Title { get; set; }

        [Required]
        [StringLength(GlobalConstants.LinkMaxLength), MinLength(GlobalConstants.LinkMinLength)]
        public string Link { get; set; }

        [MaxLength(GlobalConstants.DescriptionMaxLength)]
        public string Description { get; set; }

        [Required]
        public DateTime UploadDate { get; set; }

        [Required]
        public int EquipmentId { get; set; }

        public virtual Equipment Equipment { get; set; }

        [Required]
        [StringLength(GlobalConstants.UserIdLength)]
        public string UserId { get; set; }

        public virtual User User { get; set; }

        public ICollection&amp;amp;lt;Album&amp;amp;gt; Albums { get; set; }
    }

се пълни от този CSV (с делимитер запетайка иначе не става):

Title,Link,Description,UploadDate,EquipmentId,User
Dog,http://imgs/sample.jpg,description is lazy,25-06-2015,1,nakov
Clouds,http://imgs/sample.jpg,,25-06-2015,5,nakov
They are coming,http://imgs/sample.jpg,what's that,24-06-2015,3,alex
On the tree,http://imgs/sample.jpg,f*ck that,23-06-2015,6,nakov
Witty weather...,http://imgs/sample.jpg,description is lazy again,20-06-2015,9,alex
Angel eyes,http://imgs/sample.jpg,hihihi,18-05-2015,10,VGeorgiev
Other,http://imgs/sample.jpg,deba tova go propushanh,20-03-2015,2,alex
Dot,http://imgs/sample.jpg,softuni exammm,26-06-2015,4,VGeorgiev

с ето този seed метод

private void SeedPhotographs(ApplicationDbContext context)
{
context.Photographs.SeedFromResource("Data.Migrations.photographs.csv", p =&gt; p.Id,
    new CsvColumnMapping&lt;Photograph&gt;("User", (retObj, columnValue) =&gt;
    {
        retObj.User = context.Users.
            Single(u =&gt; u.UserName == (string)columnValue);
    }),
    new CsvColumnMapping&lt;Photograph&gt;("EquipmentId", (retObj, columnValue) =&gt;
    {
        retObj.Equipment = context.Equipments.
            FirstOrDefault(e =&gt; e.Id.ToString() == (string)columnValue);
    })
    );

context.SaveChanges();
}

и крайния резултат е:

0
29/06/2015 21:29:04
VenelinGrozev avatar VenelinGrozev 130 Точки

Би ли обяснил по-подробно откъде накъде вървят данните. От написаното излиза, че пращаш данните от таблицата към сървъра, което би трябвало да се случи с някакъв макрос а не виждам да споменаваш такъв.

От друга страна като гледам заявките са направени така че да дърпат от екселската таблица директно. Как връщаш обработените данни обратно към таблицата? През Data tab-a ли си я вързал?

0
30/06/2015 00:30:23
Kimanov avatar Kimanov 0 Точки

Точно. През Data tab-а. Стандартно вмъкване на външна таблица с посочване на сървъра и самото VIEW.

Малко по-подробно за начина, по който е решено чрез Access.

Access позволява да се създаде линк през EXTERNAL DATA менюто към таблица от Excel. След което към нея може да се обръщаш като към таблица от самата база, да обработиш данните от нея с някаква заявка, която разбира се ползва данни и от други таблици в базата. Това се записва като QUERY и след това може спокойно да бъде достъпено отново през Data tab-а в Excel. Разбира се има вариант да си викнеш данните от базата направо в Excel и там да си ги ръчкаш, но когато става дума за десетки хиляди записи и то в няколко различни таблици на базата, хич не е елегантно, а и Excel почва да се пита какво му се случва. Мястото на обработката е в базата, но възможностите на Access са доста ограничени и ако човек потърси вариант за мигриране към SQL Server изведнъж се сблъсква с проблемът, за който писах в първия пост.

 

0
30/06/2015 15:58:58
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.